@alemonjs/bubble 2.1.0-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.
package/lib/config.js ADDED
@@ -0,0 +1,34 @@
1
+ import { useUserHashKey, getConfigValue } from 'alemonjs';
2
+ import { GATEWAY_URL, API_URL, CDN_URL } from './sdk/api.js';
3
+
4
+ const platform = 'bubble';
5
+ const getBubbleConfig = () => {
6
+ const value = getConfigValue() || {};
7
+ const config = value[platform] || {};
8
+ if (!config.URL && !config.GATEWAY_URL) {
9
+ config.URL = GATEWAY_URL;
10
+ }
11
+ else if (config.GATEWAY_URL && !config.URL) {
12
+ config.URL = config.GATEWAY_URL;
13
+ }
14
+ if (!config.API_URL) {
15
+ config.API_URL = API_URL;
16
+ }
17
+ if (!config.CDN_URL) {
18
+ config.CDN_URL = CDN_URL;
19
+ }
20
+ return config;
21
+ };
22
+ const getMaster = (UserId) => {
23
+ const config = getBubbleConfig();
24
+ const masterKey = config.master_key || [];
25
+ const masterId = config.master_id || [];
26
+ const UserKey = useUserHashKey({
27
+ Platform: platform,
28
+ UserId: UserId
29
+ });
30
+ const is = masterKey.includes(UserKey) || masterId.includes(UserId);
31
+ return [is, UserKey];
32
+ };
33
+
34
+ export { getBubbleConfig, getMaster, platform };
@@ -0,0 +1 @@
1
+ export declare const activate: (context: any) => void;
package/lib/desktop.js ADDED
@@ -0,0 +1,52 @@
1
+ import { readFileSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { getConfig, getConfigValue } from 'alemonjs';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const activate = context => {
8
+ const webView = context.createSidebarWebView(context);
9
+ context.onCommand('open.bubble', () => {
10
+ const dir = join(__dirname, '../', 'dist', 'index.html');
11
+ const scriptReg = /<script.*?src="(.+?)".*?>/;
12
+ const styleReg = /<link.*?rel="stylesheet".*?href="(.+?)".*?>/;
13
+ const iconReg = /<link.*?rel="icon".*?href="(.+?)".*?>/g;
14
+ const styleUri = context.createExtensionDir(join(__dirname, '../', 'dist', 'assets', 'index.css'));
15
+ const scriptUri = context.createExtensionDir(join(__dirname, '../', 'dist', 'assets', 'index.js'));
16
+ const html = readFileSync(dir, 'utf-8')
17
+ .replace(iconReg, '')
18
+ .replace(scriptReg, `<script type="module" crossorigin src="${scriptUri}"></script>`)
19
+ .replace(styleReg, `<link rel="stylesheet" crossorigin href="${styleUri}">`);
20
+ webView.loadWebView(html);
21
+ });
22
+ webView.onMessage(data => {
23
+ try {
24
+ if (data.type === 'bubble.form.save') {
25
+ const db = data.data;
26
+ const config = getConfig();
27
+ const value = config.value ?? {};
28
+ value['bubble'] = {
29
+ token: db.token ?? '',
30
+ master_key: db.master_key?.split(',') ?? null
31
+ };
32
+ config.saveValue(value);
33
+ context.notification('bubble 配置保存成功~');
34
+ }
35
+ else if (data.type === 'bubble.init') {
36
+ let config = getConfigValue();
37
+ if (!config) {
38
+ config = {};
39
+ }
40
+ webView.postMessage({
41
+ type: 'bubble.init',
42
+ data: config.bubble ?? {}
43
+ });
44
+ }
45
+ }
46
+ catch (e) {
47
+ logger.error(e);
48
+ }
49
+ });
50
+ };
51
+
52
+ export { activate };
package/lib/hook.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ import { EventKeys, Events } from 'alemonjs';
2
+ import { BubbleAPI as API } from './sdk/api';
3
+ type MAP = {
4
+ 'message.create': object;
5
+ 'private.message.create': object;
6
+ 'interaction.create': object;
7
+ 'private.interaction.create': object;
8
+ 'message.update': undefined;
9
+ 'message.delete': undefined;
10
+ 'message.reaction.add': undefined;
11
+ 'message.reaction.remove': undefined;
12
+ 'channal.create': undefined;
13
+ 'channal.delete': undefined;
14
+ 'guild.join': undefined;
15
+ 'guild.exit': undefined;
16
+ 'member.add': undefined;
17
+ 'member.remove': undefined;
18
+ 'private.message.update': undefined;
19
+ 'private.message.delete': undefined;
20
+ 'private.friend.add': undefined;
21
+ 'private.guild.add': undefined;
22
+ };
23
+ export declare const useValue: <T extends EventKeys>(event: Events[T]) => readonly [MAP[T]];
24
+ export declare const useClient: <T extends EventKeys>(event: Events[T]) => readonly [API, MAP[T]];
25
+ export {};
package/lib/hook.js ADDED
@@ -0,0 +1,14 @@
1
+ import { createEventValue, useClient as useClient$1 } from 'alemonjs';
2
+ import { BubbleAPI } from './sdk/api.js';
3
+
4
+ const useValue = (event) => {
5
+ const value = createEventValue(event);
6
+ return [value];
7
+ };
8
+ const useClient = (event) => {
9
+ const [client] = useClient$1(event, BubbleAPI);
10
+ const value = createEventValue(event);
11
+ return [client, value];
12
+ };
13
+
14
+ export { useClient, useValue };
package/lib/index.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export { platform } from './config';
2
+ export { BubbleAPI as API } from './sdk/api';
3
+ export { API_URL, CDN_URL, GATEWAY_URL } from './sdk/api';
4
+ export type { IntentsEnum, User, Channel, Guild, Attachment, BaseMessage, MessageCreateEvent, DmMessageCreateEvent, MessageUpdateEvent, MessageDeleteEvent, GuildMemberEvent, BotReadyEvent, EventsSubscribedEvent, EventsUnsubscribedEvent, SubscribeDeniedEvent, BotInfo, SendMessagePayload, FileUploadResponse, FileQuota, BubbleEventMap } from './sdk/types';
5
+ export { BubbleClient } from './sdk/wss';
6
+ export { OpCode } from './sdk/wss.types';
7
+ export type { BUBBLEOptions, HelloPayload, SubscribePayload } from './sdk/wss.types';
8
+ export * from './hook';
9
+ export { type Options } from './config';
10
+ declare const main: () => void;
11
+ export default main;
package/lib/index.js ADDED
@@ -0,0 +1,223 @@
1
+ import { BubbleClient } from './sdk/wss.js';
2
+ import { cbpPlatform, createResult, ResultCode } from 'alemonjs';
3
+ import { getMaster, platform } from './config.js';
4
+ import { CDN_URL } from './sdk/api.js';
5
+ export { BubbleAPI as API, API_URL, GATEWAY_URL } from './sdk/api.js';
6
+ import { sendchannel, senduser } from './send.js';
7
+ export { OpCode } from './sdk/wss.types.js';
8
+ export { useClient, useValue } from './hook.js';
9
+
10
+ const main = () => {
11
+ const port = process.env?.port || 17117;
12
+ const url = `ws://127.0.0.1:${port}`;
13
+ const cbp = cbpPlatform(url);
14
+ const client = new BubbleClient();
15
+ void client.connect();
16
+ const createUserAvatar = (_UserId, avatar) => {
17
+ return `${CDN_URL}/${avatar}`;
18
+ };
19
+ client.on('MESSAGE_CREATE', event => {
20
+ if (event.author?.bot) {
21
+ return;
22
+ }
23
+ const atUsers = [];
24
+ for (const item of event.mentions || []) {
25
+ atUsers.push({
26
+ id: String(item.id)
27
+ });
28
+ }
29
+ let msg = event.content;
30
+ for (const item of atUsers) {
31
+ msg = msg.replace(`<@${item.id}>`, '').trim();
32
+ }
33
+ const UserId = String(event.author.id);
34
+ const [isMaster, UserKey] = getMaster(UserId);
35
+ const UserAvatar = createUserAvatar(UserId, event.author.avatar);
36
+ if (event.type === 0 && event.member) {
37
+ const e = {
38
+ name: 'message.create',
39
+ Platform: platform,
40
+ GuildId: String(event.guild_id || ''),
41
+ ChannelId: String(event.channel_id || ''),
42
+ SpaceId: String(event.channel_id || ''),
43
+ UserId: UserId,
44
+ UserKey,
45
+ UserName: event.author.username,
46
+ UserAvatar: UserAvatar,
47
+ IsMaster: isMaster,
48
+ IsBot: false,
49
+ OpenId: UserId,
50
+ MessageId: String(event.id),
51
+ MessageText: msg,
52
+ CreateAt: Date.now(),
53
+ tag: 'message.create',
54
+ value: event
55
+ };
56
+ cbp.send(e);
57
+ }
58
+ else if (event.type === 0 && !event.member) {
59
+ const e = {
60
+ name: 'private.message.create',
61
+ Platform: platform,
62
+ UserId: UserId,
63
+ UserKey,
64
+ UserName: event.author.username,
65
+ UserAvatar: UserAvatar,
66
+ IsMaster: isMaster,
67
+ IsBot: false,
68
+ OpenId: UserId,
69
+ MessageId: String(event.id),
70
+ MessageText: msg,
71
+ CreateAt: Date.now(),
72
+ tag: 'private.message.create',
73
+ value: event
74
+ };
75
+ cbp.send(e);
76
+ }
77
+ else ;
78
+ });
79
+ const api = {
80
+ active: {
81
+ send: {
82
+ channel: async (UserId, val) => {
83
+ const res = await sendchannel(client, { channel_id: UserId }, val);
84
+ return [createResult(ResultCode.Ok, '请求完成', res)];
85
+ },
86
+ user: async (OpenId, val) => {
87
+ const res = await senduser(client, { author_id: OpenId }, val);
88
+ return [createResult(ResultCode.Ok, '请求完成', res)];
89
+ }
90
+ }
91
+ },
92
+ use: {
93
+ send: async (event, val) => {
94
+ if (val.length < 0) {
95
+ return [];
96
+ }
97
+ const tag = event.tag;
98
+ if (tag === 'message.create') {
99
+ const ChannelId = String(event.value.channel_id || '');
100
+ const res = await sendchannel(client, { channel_id: ChannelId }, val);
101
+ return [createResult(ResultCode.Ok, '请求完成', res)];
102
+ }
103
+ else if (tag === 'private.message.create') {
104
+ const UserId = String(event.value.author.id || '');
105
+ const ChannelId = String(event.value.channel_id || '');
106
+ const res = await senduser(client, {
107
+ channel_id: ChannelId,
108
+ author_id: UserId
109
+ }, val);
110
+ return [createResult(ResultCode.Ok, '请求完成', res)];
111
+ }
112
+ else if (tag === 'interaction.create') {
113
+ const ChannelId = String(event.value.channel_id || '');
114
+ const res = await sendchannel(client, { channel_id: ChannelId }, val);
115
+ return [createResult(ResultCode.Ok, '请求完成', res)];
116
+ }
117
+ else if (tag === 'private.interaction.create') {
118
+ const UserId = String(event.value.user.id || '');
119
+ const ChannelId = String(event.value.channel_id || '');
120
+ const res = await senduser(client, {
121
+ channel_id: ChannelId,
122
+ author_id: UserId
123
+ }, val);
124
+ return [createResult(ResultCode.Ok, '请求完成', res)];
125
+ }
126
+ return [];
127
+ },
128
+ mention: e => {
129
+ const event = e.value;
130
+ const MessageMention = event.mentions.map(item => {
131
+ const UserId = item.id;
132
+ const avatar = event.author.avatar;
133
+ const UserAvatar = createUserAvatar(UserId, avatar);
134
+ const [isMaster, UserKey] = getMaster(UserId);
135
+ return {
136
+ UserId: item.id,
137
+ IsMaster: isMaster,
138
+ IsBot: item.bot,
139
+ UserAvatar,
140
+ UserKey
141
+ };
142
+ });
143
+ return new Promise(resolve => {
144
+ resolve(MessageMention);
145
+ });
146
+ }
147
+ }
148
+ };
149
+ const onactions = async (data, consume) => {
150
+ try {
151
+ if (data.action === 'message.send') {
152
+ const event = data.payload.event;
153
+ const paramFormat = data.payload.params.format;
154
+ const res = await api.use.send(event, paramFormat);
155
+ consume(res);
156
+ }
157
+ else if (data.action === 'message.send.channel') {
158
+ const channelId = data.payload.ChannelId;
159
+ const val = data.payload.params.format;
160
+ const res = await api.active.send.channel(channelId, val);
161
+ consume(res);
162
+ }
163
+ else if (data.action === 'message.send.user') {
164
+ const userId = data.payload.UserId;
165
+ const val = data.payload.params.format;
166
+ const res = await api.active.send.user(userId, val);
167
+ consume(res);
168
+ }
169
+ else if (data.action === 'mention.get') {
170
+ const event = data.payload.event;
171
+ const res = await api.use.mention(event);
172
+ consume([createResult(ResultCode.Ok, '请求完成', res)]);
173
+ }
174
+ }
175
+ catch (error) {
176
+ consume([createResult(ResultCode.Fail, '请求失败', error)]);
177
+ }
178
+ };
179
+ cbp.onactions((data, consume) => void onactions(data, consume));
180
+ const onapis = async (data, consume) => {
181
+ const key = data.payload?.key;
182
+ if (client[key]) {
183
+ const params = data.payload.params;
184
+ try {
185
+ const res = await client[key](...params);
186
+ consume([createResult(ResultCode.Ok, '请求完成', res)]);
187
+ }
188
+ catch (error) {
189
+ consume([createResult(ResultCode.Fail, '请求失败', error)]);
190
+ }
191
+ }
192
+ };
193
+ cbp.onapis((data, consume) => void onapis(data, consume));
194
+ };
195
+ const mainProcess = () => {
196
+ ['SIGINT', 'SIGTERM', 'SIGQUIT', 'disconnect'].forEach(sig => {
197
+ process?.on?.(sig, () => {
198
+ logger.info?.(`[alemonjs][${sig}] 收到信号,正在关闭...`);
199
+ setImmediate(() => process.exit(0));
200
+ });
201
+ });
202
+ process?.on?.('exit', code => {
203
+ logger.info?.(`[alemonjs][exit] 进程退出,code=${code}`);
204
+ });
205
+ process.on('message', msg => {
206
+ try {
207
+ const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
208
+ if (data?.type === 'start') {
209
+ main();
210
+ }
211
+ else if (data?.type === 'stop') {
212
+ process.exit(0);
213
+ }
214
+ }
215
+ catch { }
216
+ });
217
+ if (process.send) {
218
+ process.send(JSON.stringify({ type: 'ready' }));
219
+ }
220
+ };
221
+ mainProcess();
222
+
223
+ export { BubbleClient, CDN_URL, main as default, platform };
@@ -0,0 +1,29 @@
1
+ import { type AxiosRequestConfig } from 'axios';
2
+ import type { BotInfo, SendMessagePayload, FileUploadResponse, FileQuota, BaseMessage, Channel, User } from './types.js';
3
+ export declare const API_URL: string;
4
+ export declare const CDN_URL: string;
5
+ export declare const GATEWAY_URL: string;
6
+ export declare class BubbleAPI {
7
+ request(options: AxiosRequestConfig): Promise<any>;
8
+ getMe(): Promise<BotInfo>;
9
+ sendMessage(channelId: string | number, data: SendMessagePayload): Promise<BaseMessage>;
10
+ getChannelMessages(channelId: string | number): Promise<BaseMessage[]>;
11
+ editMessage(channelId: string | number, messageId: string | number, data: Partial<SendMessagePayload>): Promise<BaseMessage>;
12
+ deleteMessage(channelId: string | number, messageId: string | number): Promise<void>;
13
+ listGuildChannels(guildId: string | number): Promise<Channel[]>;
14
+ getChannel(channelId: string | number): Promise<Channel>;
15
+ listGuildMembers(guildId: string | number): Promise<User[]>;
16
+ getGuildMember(guildId: string | number, userId: string | number): Promise<User>;
17
+ getOrCreateDm(userId: string | number): Promise<{
18
+ id: number;
19
+ type: string;
20
+ }>;
21
+ sendDm(threadId: string | number, data: SendMessagePayload): Promise<BaseMessage>;
22
+ getDmMessages(threadId: string | number): Promise<BaseMessage[]>;
23
+ uploadFile(file: any, filename?: string, extra?: {
24
+ channelId?: string | number;
25
+ threadId?: string | number;
26
+ messageId?: string | number;
27
+ }): Promise<FileUploadResponse>;
28
+ filesQuota(): Promise<FileQuota>;
29
+ }
package/lib/sdk/api.js ADDED
@@ -0,0 +1,99 @@
1
+ import axios from 'axios';
2
+ import { getBubbleConfig } from '../config.js';
3
+ import { HttpsProxyAgent } from 'https-proxy-agent';
4
+ import { createAxiosInstance } from './instance.js';
5
+
6
+ const API_URL = process.env.BUBBLE_API_BASE || 'https://bubble.alemonjs.com/api/bot/v1';
7
+ const CDN_URL = process.env.BUBBLE_CDN_BASE || 'https://bubble-oss-files.alemonjs.com';
8
+ const GATEWAY_URL = process.env.BUBBLE_GATEWAY_URL || 'wss://bubble.alemonjs.com/api/bot/gateway';
9
+ class BubbleAPI {
10
+ request(options) {
11
+ const value = getBubbleConfig();
12
+ const token = value.token;
13
+ const requestConfig = value.request_config ?? {};
14
+ if (value.request_proxy) {
15
+ requestConfig.httpsAgent = new HttpsProxyAgent(value.request_proxy);
16
+ }
17
+ const service = axios.create({
18
+ ...requestConfig,
19
+ baseURL: API_URL,
20
+ timeout: 6000,
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ Authorization: `Bearer ${token}`
24
+ }
25
+ });
26
+ return createAxiosInstance(service, options);
27
+ }
28
+ getMe() {
29
+ return this.request({ method: 'GET', url: '/me' });
30
+ }
31
+ sendMessage(channelId, data) {
32
+ return this.request({ method: 'POST', url: `/channels/${channelId}/messages`, data });
33
+ }
34
+ getChannelMessages(channelId) {
35
+ return this.request({ method: 'GET', url: `/channels/${channelId}/messages` });
36
+ }
37
+ editMessage(channelId, messageId, data) {
38
+ return this.request({ method: 'PUT', url: `/channels/${channelId}/messages/${messageId}`, data });
39
+ }
40
+ deleteMessage(channelId, messageId) {
41
+ return this.request({ method: 'DELETE', url: `/channels/${channelId}/messages/${messageId}` });
42
+ }
43
+ listGuildChannels(guildId) {
44
+ return this.request({ method: 'GET', url: `/guilds/${guildId}/channels` });
45
+ }
46
+ getChannel(channelId) {
47
+ return this.request({ method: 'GET', url: `/channels/${channelId}` });
48
+ }
49
+ listGuildMembers(guildId) {
50
+ return this.request({ method: 'GET', url: `/guilds/${guildId}/members` });
51
+ }
52
+ getGuildMember(guildId, userId) {
53
+ return this.request({ method: 'GET', url: `/guilds/${guildId}/members/${userId}` });
54
+ }
55
+ getOrCreateDm(userId) {
56
+ return this.request({ method: 'GET', url: `/users/${userId}/dm` });
57
+ }
58
+ sendDm(threadId, data) {
59
+ return this.request({ method: 'POST', url: `/dm/threads/${threadId}/messages`, data });
60
+ }
61
+ getDmMessages(threadId) {
62
+ return this.request({ method: 'GET', url: `/dm/threads/${threadId}/messages` });
63
+ }
64
+ async uploadFile(file, filename, extra = {}) {
65
+ const FormData = (await import('form-data')).default;
66
+ const form = new FormData();
67
+ form.append('file', file, filename || 'file');
68
+ if (extra.channelId) {
69
+ form.append('channelId', String(extra.channelId));
70
+ }
71
+ if (extra.threadId) {
72
+ form.append('threadId', String(extra.threadId));
73
+ }
74
+ if (extra.messageId) {
75
+ form.append('messageId', String(extra.messageId));
76
+ }
77
+ const value = getBubbleConfig();
78
+ const token = value.token;
79
+ const requestConfig = value.request_config ?? {};
80
+ if (value.request_proxy) {
81
+ requestConfig.httpsAgent = new HttpsProxyAgent(value.request_proxy);
82
+ }
83
+ const service = axios.create({
84
+ ...requestConfig,
85
+ baseURL: API_URL,
86
+ timeout: 60000,
87
+ headers: {
88
+ Authorization: `Bearer ${token}`,
89
+ ...form.getHeaders()
90
+ }
91
+ });
92
+ return createAxiosInstance(service, { method: 'POST', url: '/files/upload', data: form });
93
+ }
94
+ filesQuota() {
95
+ return this.request({ method: 'GET', url: '/files/quota' });
96
+ }
97
+ }
98
+
99
+ export { API_URL, BubbleAPI, CDN_URL, GATEWAY_URL };
@@ -0,0 +1,6 @@
1
+ import { Readable } from 'stream';
2
+ export declare function createPicFrom(image: string | Buffer | Readable, name?: string): Promise<false | {
3
+ picData: Readable;
4
+ image: string | Readable | Buffer<ArrayBufferLike>;
5
+ name: string;
6
+ }>;
@@ -0,0 +1,37 @@
1
+ import { existsSync, createReadStream } from 'fs';
2
+ import { Readable, isReadable } from 'stream';
3
+ import { basename } from 'path';
4
+ import { fileTypeFromBuffer, fileTypeFromStream } from 'file-type';
5
+
6
+ async function createPicFrom(image, name = 'image.jpg') {
7
+ let picData;
8
+ if (typeof image === 'string') {
9
+ if (!existsSync(image)) {
10
+ return false;
11
+ }
12
+ if (!name) {
13
+ name = basename(image);
14
+ }
15
+ picData = createReadStream(image);
16
+ }
17
+ else if (Buffer.isBuffer(image)) {
18
+ if (!name) {
19
+ name = 'file.' + (await fileTypeFromBuffer(image)).ext;
20
+ }
21
+ picData = new Readable();
22
+ picData.push(image);
23
+ picData.push(null);
24
+ }
25
+ else if (isReadable(image)) {
26
+ if (!name) {
27
+ name = 'file.' + (await fileTypeFromStream(image)).ext;
28
+ }
29
+ picData = image;
30
+ }
31
+ else {
32
+ return false;
33
+ }
34
+ return { picData, image, name };
35
+ }
36
+
37
+ export { createPicFrom };
@@ -0,0 +1,3 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { type AxiosRequestConfig } from 'axios';
3
+ export declare const createAxiosInstance: (service: AxiosInstance, options: AxiosRequestConfig) => Promise<any>;
@@ -0,0 +1,93 @@
1
+ const filterHeaders = (headers = {}) => {
2
+ if (!headers) {
3
+ return headers;
4
+ }
5
+ const filtered = {};
6
+ const sensitiveKeys = [/^authorization$/i, /^cookie$/i, /^set-cookie$/i, /token/i, /key/i, /jwt/i, /^session[-_]id$/i, /^uid$/i, /^user[-_]id$/i];
7
+ for (const key in headers) {
8
+ if (/^_/.test(key)) {
9
+ continue;
10
+ }
11
+ if (typeof key === 'symbol') {
12
+ continue;
13
+ }
14
+ if (typeof headers[key] === 'function') {
15
+ continue;
16
+ }
17
+ if (sensitiveKeys.some(re => re.test(key))) {
18
+ filtered[key] = '******';
19
+ }
20
+ else {
21
+ filtered[key] = headers[key];
22
+ }
23
+ }
24
+ return filtered;
25
+ };
26
+ const filterConfig = (config = {}) => {
27
+ if (!config) {
28
+ return config;
29
+ }
30
+ const filtered = {};
31
+ for (const key in config) {
32
+ if (/^_/.test(key)) {
33
+ continue;
34
+ }
35
+ if (typeof key === 'symbol') {
36
+ continue;
37
+ }
38
+ if (typeof config[key] === 'function') {
39
+ continue;
40
+ }
41
+ filtered[key] = config[key];
42
+ }
43
+ return filtered;
44
+ };
45
+ const filterRequest = (request = {}) => {
46
+ if (!request) {
47
+ return request;
48
+ }
49
+ const filtered = {};
50
+ for (const key in request) {
51
+ if (/^_/.test(key)) {
52
+ continue;
53
+ }
54
+ if (typeof key === 'symbol') {
55
+ continue;
56
+ }
57
+ if (typeof request[key] === 'function') {
58
+ continue;
59
+ }
60
+ filtered[key] = request[key];
61
+ }
62
+ return filtered;
63
+ };
64
+ const loggerError = err => {
65
+ logger.error('[axios] error', {
66
+ config: {
67
+ headers: filterHeaders(err?.config?.headers),
68
+ params: err?.config?.params,
69
+ data: err?.config?.data
70
+ },
71
+ response: {
72
+ status: err?.response?.status,
73
+ statusText: err?.response?.statusText,
74
+ headers: filterHeaders(err?.response?.headers),
75
+ config: filterConfig(err?.response?.config),
76
+ request: filterRequest(err?.response?.request),
77
+ data: err?.response?.data
78
+ },
79
+ message: err?.message
80
+ });
81
+ };
82
+ const createAxiosInstance = (service, options) => {
83
+ return new Promise((resolve, reject) => {
84
+ service(options)
85
+ .then(res => resolve(res?.data ?? {}))
86
+ .catch(err => {
87
+ loggerError(err);
88
+ reject(err?.response?.data);
89
+ });
90
+ });
91
+ };
92
+
93
+ export { createAxiosInstance };