@typexim/web-sdk 0.0.6 → 0.0.8-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +10 -3
  2. package/dist/types/enums/sdk.d.ts +0 -1
  3. package/dist/types/interfaces/business.d.ts +45 -1
  4. package/dist/types/interfaces/sdk/api.d.ts +41 -1
  5. package/dist/types/modules/ChatSDK.d.ts +24 -3
  6. package/dist/types/modules/TabSessionCoordinator.d.ts +5 -5
  7. package/dist/types/utils/misc.d.ts +10 -0
  8. package/dist/web-sdk.esm.js +1 -1
  9. package/dist/web-sdk.js +1 -1
  10. package/dist-test/enums/business.js +139 -0
  11. package/dist-test/enums/index.js +2 -0
  12. package/dist-test/enums/sdk.js +24 -0
  13. package/dist-test/events.js +50 -0
  14. package/dist-test/index.js +26 -0
  15. package/dist-test/interfaces/business.js +1 -0
  16. package/dist-test/interfaces/index.js +3 -0
  17. package/dist-test/interfaces/pushMessage.js +1 -0
  18. package/dist-test/interfaces/sdk/api.js +1 -0
  19. package/dist-test/interfaces/sdk/common.js +1 -0
  20. package/dist-test/interfaces/sdk/index.js +2 -0
  21. package/dist-test/modules/Base.js +70 -0
  22. package/dist-test/modules/BusinessWebsocket.js +68 -0
  23. package/dist-test/modules/ChatSDK.js +698 -0
  24. package/dist-test/modules/FeedCache.js +211 -0
  25. package/dist-test/modules/HttpClient.js +104 -0
  26. package/dist-test/modules/Logger.js +73 -0
  27. package/dist-test/modules/PushMessageProcessor.js +437 -0
  28. package/dist-test/modules/ReConnectWebsocket.js +223 -0
  29. package/dist-test/modules/Storage.js +27 -0
  30. package/dist-test/modules/TabSessionCoordinator.js +289 -0
  31. package/dist-test/modules/Version.js +20 -0
  32. package/dist-test/utils/date.js +4 -0
  33. package/dist-test/utils/http.js +13 -0
  34. package/dist-test/utils/makeSign.js +79 -0
  35. package/dist-test/utils/message.js +146 -0
  36. package/dist-test/utils/misc.js +13 -0
  37. package/dist-test/utils/promise.js +10 -0
  38. package/dist-test/utils/sleep.js +3 -0
  39. package/dist-test/utils/websocket.js +24 -0
  40. package/package.json +3 -2
  41. package/test/chat-sdk-independent-login.test.mjs +218 -0
  42. package/test/{chat-sdk-restore-login.test.mjs → chat-sdk-session-restore.test.mjs} +69 -29
  43. package/test/tab-session-coordinator.test.mjs +30 -64
  44. package/dist/types/modules/SingletonLock.d.ts +0 -12
  45. package/test/singleton-lock.test.mjs +0 -75
@@ -0,0 +1,211 @@
1
+ import { FeedType } from '../enums/index.js';
2
+ import { withResolvers } from '../utils/promise.js';
3
+ export default class FeedCache {
4
+ constructor() {
5
+ Object.defineProperty(this, "syncCompleted", {
6
+ enumerable: true,
7
+ configurable: true,
8
+ writable: true,
9
+ value: void 0
10
+ });
11
+ // feed_id -> Feed
12
+ Object.defineProperty(this, "map", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ // chat_id -> feed_id
19
+ Object.defineProperty(this, "chatMap", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: void 0
24
+ });
25
+ // thread_id -> feed_id
26
+ Object.defineProperty(this, "threadMap", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: void 0
31
+ });
32
+ // target_id -> feed_id
33
+ Object.defineProperty(this, "targetMap", {
34
+ enumerable: true,
35
+ configurable: true,
36
+ writable: true,
37
+ value: void 0
38
+ });
39
+ Object.defineProperty(this, "list", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: void 0
44
+ });
45
+ Object.defineProperty(this, "waitMap", {
46
+ enumerable: true,
47
+ configurable: true,
48
+ writable: true,
49
+ value: void 0
50
+ });
51
+ this.syncCompleted = false;
52
+ this.map = new Map();
53
+ this.chatMap = new Map();
54
+ this.threadMap = new Map();
55
+ this.targetMap = new Map();
56
+ this.waitMap = new Map();
57
+ this.list = [];
58
+ }
59
+ getAll() {
60
+ const result = [];
61
+ for (const id of this.list) {
62
+ const feed = this.map.get(id);
63
+ if (feed) {
64
+ result.push(feed);
65
+ }
66
+ }
67
+ return result;
68
+ }
69
+ get(feedId) {
70
+ return this.map.get(feedId) ?? null;
71
+ }
72
+ getByChat(chatId, threadId) {
73
+ let feedId;
74
+ if (threadId && threadId !== '0') {
75
+ feedId = this.threadMap.get(threadId);
76
+ }
77
+ else {
78
+ feedId = this.chatMap.get(chatId);
79
+ }
80
+ if (feedId !== undefined) {
81
+ return this.get(feedId);
82
+ }
83
+ return null;
84
+ }
85
+ getByTargetId(targetId) {
86
+ const set = this.targetMap.get(targetId);
87
+ if (set === undefined) {
88
+ return [];
89
+ }
90
+ const list = [];
91
+ for (const id of set) {
92
+ const feed = this.get(id);
93
+ if (feed !== null) {
94
+ list.push(feed);
95
+ }
96
+ }
97
+ return list;
98
+ }
99
+ async waitFor(feedId) {
100
+ const feed = this.get(feedId);
101
+ if (feed) {
102
+ return feed;
103
+ }
104
+ if (this.syncCompleted) {
105
+ return null;
106
+ }
107
+ let resolver = this.waitMap.get(feedId);
108
+ if (!resolver) {
109
+ resolver = withResolvers();
110
+ this.waitMap.set(feedId, resolver);
111
+ }
112
+ await resolver.promise;
113
+ return this.get(feedId);
114
+ }
115
+ resolveWait(feedId) {
116
+ const resolver = this.waitMap.get(feedId);
117
+ if (resolver) {
118
+ resolver.resolve();
119
+ this.waitMap.delete(feedId);
120
+ }
121
+ }
122
+ removeFromList(feedId) {
123
+ const index = this.list.indexOf(feedId);
124
+ if (index > -1) {
125
+ this.list.splice(index, 1);
126
+ }
127
+ }
128
+ remove(feedId) {
129
+ const feed = this.map.get(feedId);
130
+ if (feed) {
131
+ this.map.delete(feedId);
132
+ if (feed.feed_type === FeedType.thread) {
133
+ this.threadMap.delete(feed.thread_id);
134
+ }
135
+ else {
136
+ this.chatMap.delete(feed.chat_id);
137
+ if (feed.target_id && feed.target_id !== '0') {
138
+ const set = this.targetMap.get(feed.target_id);
139
+ if (set !== undefined) {
140
+ set.delete(feed.id);
141
+ if (set.size === 0) {
142
+ this.targetMap.delete(feed.target_id);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ this.removeFromList(feedId);
148
+ return true;
149
+ }
150
+ return false;
151
+ }
152
+ beforeSave(feed) {
153
+ if (this.map.has(feed.id)) {
154
+ this.removeFromList(feed.id);
155
+ }
156
+ else {
157
+ if (feed.feed_type === FeedType.thread) {
158
+ this.threadMap.set(feed.thread_id, feed.id);
159
+ }
160
+ else {
161
+ this.chatMap.set(feed.chat_id, feed.id);
162
+ if (feed.target_id && feed.target_id !== '0') {
163
+ if (!this.targetMap.has(feed.target_id)) {
164
+ const set = new Set();
165
+ this.targetMap.set(feed.target_id, set);
166
+ }
167
+ this.targetMap.get(feed.target_id)?.add(feed.id);
168
+ }
169
+ }
170
+ }
171
+ this.map.set(feed.id, feed);
172
+ }
173
+ afterSave(feed) {
174
+ this.resolveWait(feed.id);
175
+ }
176
+ push(feed) {
177
+ this.beforeSave(feed);
178
+ this.list.push(feed.id);
179
+ this.afterSave(feed);
180
+ }
181
+ unshift(feed) {
182
+ this.beforeSave(feed);
183
+ this.list.unshift(feed.id);
184
+ this.afterSave(feed);
185
+ }
186
+ update(feed) {
187
+ if (!this.map.has(feed.id)) {
188
+ return;
189
+ }
190
+ this.map.set(feed.id, feed);
191
+ }
192
+ markSyncComplete() {
193
+ this.syncCompleted = true;
194
+ for (const [_, resolver] of this.waitMap) {
195
+ resolver.resolve();
196
+ }
197
+ this.waitMap.clear();
198
+ }
199
+ isSyncCompleted() {
200
+ return this.syncCompleted;
201
+ }
202
+ reset() {
203
+ this.syncCompleted = false;
204
+ this.map.clear();
205
+ this.chatMap.clear();
206
+ this.threadMap.clear();
207
+ this.targetMap.clear();
208
+ this.waitMap.clear();
209
+ this.list = [];
210
+ }
211
+ }
@@ -0,0 +1,104 @@
1
+ import axios from 'axios';
2
+ import { HttpClientResponseCode } from '../enums/index.js';
3
+ import { createErrorResponse } from '../utils/http.js';
4
+ import makeSign from '../utils/makeSign.js';
5
+ function createMakeSignErrorResponse() {
6
+ return createErrorResponse(HttpClientResponseCode.MAKE_SIGN_FAIL, 'make sign fail');
7
+ }
8
+ export default class HttpClient {
9
+ constructor(config) {
10
+ Object.defineProperty(this, "api", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: void 0
15
+ });
16
+ Object.defineProperty(this, "context", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: void 0
21
+ });
22
+ Object.defineProperty(this, "logger", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ this.api = axios.create({
29
+ baseURL: config.host,
30
+ headers: {
31
+ 'x-developer': config.developer,
32
+ },
33
+ withCredentials: true,
34
+ });
35
+ this.context = config.context;
36
+ this.logger = config.logger;
37
+ }
38
+ async request(config) {
39
+ try {
40
+ const { needSign = true, ...axiosConfig } = config;
41
+ if (!axiosConfig.headers) {
42
+ axiosConfig.headers = {};
43
+ }
44
+ axiosConfig.headers['platform'] = 'web';
45
+ if (needSign &&
46
+ config.method?.toUpperCase() === 'POST' &&
47
+ axiosConfig.data) {
48
+ if (this.context.loginUser === null) {
49
+ this.logger.warn('HttpClient needs make sign but not login');
50
+ return createMakeSignErrorResponse();
51
+ }
52
+ try {
53
+ const sign = await makeSign(axiosConfig.data, this.context.loginUser.secretKey);
54
+ axiosConfig.headers['sign'] = sign;
55
+ }
56
+ catch (e) {
57
+ this.logger.error('HttpClient make sign error', e);
58
+ return createMakeSignErrorResponse();
59
+ }
60
+ }
61
+ if (this.context.loginUser) {
62
+ axiosConfig.headers['X-Sid'] = this.context.loginUser.sessionId;
63
+ }
64
+ const res = await this.api(axiosConfig);
65
+ const body = res.data;
66
+ if (body.code === HttpClientResponseCode.SUCCESS) {
67
+ return {
68
+ ok: true,
69
+ data: body.data,
70
+ };
71
+ }
72
+ this.logger.info('HttpClient server error', res);
73
+ return {
74
+ ok: false,
75
+ code: body.code,
76
+ msg: body.msg,
77
+ msg_i18n: body.msg_i18n,
78
+ };
79
+ }
80
+ catch {
81
+ return {
82
+ ok: false,
83
+ code: HttpClientResponseCode.NETWORK_ERROR,
84
+ msg: 'network error',
85
+ };
86
+ }
87
+ }
88
+ get(url, params, config) {
89
+ return this.request({
90
+ url,
91
+ method: 'GET',
92
+ params,
93
+ ...config,
94
+ });
95
+ }
96
+ post(url, data, config) {
97
+ return this.request({
98
+ url,
99
+ method: 'POST',
100
+ data,
101
+ ...config,
102
+ });
103
+ }
104
+ }
@@ -0,0 +1,73 @@
1
+ import { LogLevel } from '../enums/index.js';
2
+ function padNumStart(num) {
3
+ return `${num}`.padStart(2, '0');
4
+ }
5
+ export default class Logger {
6
+ constructor() {
7
+ Object.defineProperty(this, "level", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: void 0
12
+ });
13
+ Object.defineProperty(this, "logHandler", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: void 0
18
+ });
19
+ this.level = LogLevel.error;
20
+ this.logHandler = this.createLogHandler();
21
+ }
22
+ getPriority(level) {
23
+ switch (level) {
24
+ case LogLevel.error:
25
+ return 3;
26
+ case LogLevel.warning:
27
+ return 2;
28
+ case LogLevel.info:
29
+ return 1;
30
+ default:
31
+ return 0;
32
+ }
33
+ }
34
+ createLogHandler() {
35
+ return (level, ...args) => {
36
+ const date = new Date();
37
+ const timestamp = `${date.getFullYear()}-${padNumStart(date.getMonth() + 1)}-${padNumStart(date.getDate())} ${padNumStart(date.getHours())}:${padNumStart(date.getMinutes())}:${padNumStart(date.getSeconds())}.${date.getMilliseconds()}`;
38
+ const prefix = `TypeX >> [${timestamp}]`;
39
+ switch (level) {
40
+ case LogLevel.error:
41
+ console.error(prefix, '[ERR]', ...args);
42
+ break;
43
+ case LogLevel.warning:
44
+ console.warn(prefix, '[WARN]', ...args);
45
+ break;
46
+ case LogLevel.info:
47
+ console.info(prefix, '[INFO]', ...args);
48
+ break;
49
+ default:
50
+ console.log(prefix, ...args);
51
+ }
52
+ };
53
+ }
54
+ log(level, ...args) {
55
+ if (this.getPriority(level) >= this.getPriority(this.level)) {
56
+ this.logHandler(level, ...args);
57
+ }
58
+ }
59
+ setLogLevel(level) {
60
+ this.level = level;
61
+ // 重新创建logHandler以确保使用新的日志级别
62
+ this.logHandler = this.createLogHandler();
63
+ }
64
+ info(...args) {
65
+ this.log(LogLevel.info, ...args);
66
+ }
67
+ warn(...args) {
68
+ this.log(LogLevel.warning, ...args);
69
+ }
70
+ error(...args) {
71
+ this.log(LogLevel.error, ...args);
72
+ }
73
+ }