@lark-apaas/client-toolkit 1.2.9 → 1.2.34
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/antd-table.d.ts +2 -2
- package/lib/apis/aily-chat.d.ts +2 -0
- package/lib/apis/aily-chat.js +2 -0
- package/lib/apis/hooks/useScrollReveal.d.ts +1 -0
- package/lib/apis/hooks/useScrollReveal.js +1 -0
- package/lib/apis/udt-types.d.ts +4 -0
- package/lib/apis/utils/resolveAppUrl.d.ts +1 -0
- package/lib/apis/utils/resolveAppUrl.js +2 -0
- package/lib/apis/utils/scopedStorage.d.ts +1 -0
- package/lib/apis/utils/scopedStorage.js +2 -0
- package/lib/auth.d.ts +2 -1
- package/lib/auth.js +2 -2
- package/lib/components/AppContainer/api-proxy/core.js +2 -1
- package/lib/components/AppContainer/index.d.ts +5 -1
- package/lib/components/AppContainer/index.js +41 -34
- package/lib/components/AppContainer/safety.js +27 -8
- package/lib/components/AppContainer/utils/childApi.js +1 -0
- package/lib/components/AppContainer/utils/getLarkUser.js +4 -2
- package/lib/components/AppContainer/utils/observable.js +7 -1
- package/lib/components/AppContainer/utils/tea.js +1 -1
- package/lib/components/ErrorRender/index.js +5 -11
- package/lib/components/User/UserSelect.js +1 -13
- package/lib/components/theme/index.d.ts +0 -1
- package/lib/components/theme/index.js +0 -1
- package/lib/components/theme/util.d.ts +0 -2
- package/lib/components/theme/util.js +0 -108
- package/lib/components/ui/badge.d.ts +1 -1
- package/lib/components/ui/button.d.ts +2 -2
- package/lib/components/ui/button.js +1 -1
- package/lib/components/ui/confirm.d.ts +28 -0
- package/lib/components/ui/confirm.js +83 -0
- package/lib/components/ui/toast.d.ts +2 -0
- package/lib/components/ui/toast.js +53 -0
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/useCurrentUserProfile.d.ts +18 -3
- package/lib/hooks/useCurrentUserProfile.js +38 -29
- package/lib/hooks/useLogout.js +2 -17
- package/lib/hooks/useScrollReveal.d.ts +61 -0
- package/lib/hooks/useScrollReveal.js +37 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +14 -2
- package/lib/integrations/dataloom.d.ts +3 -1
- package/lib/integrations/dataloom.js +18 -10
- package/lib/integrations/getCurrentUserProfile.d.ts +7 -1
- package/lib/integrations/services/ChatService.d.ts +12 -0
- package/lib/integrations/services/ChatService.js +67 -0
- package/lib/integrations/services/DepartmentService.js +3 -2
- package/lib/integrations/services/UserProfileService.js +3 -2
- package/lib/integrations/services/UserService.d.ts +3 -1
- package/lib/integrations/services/UserService.js +23 -3
- package/lib/integrations/services/index.d.ts +1 -0
- package/lib/integrations/services/index.js +1 -0
- package/lib/integrations/services/types.d.ts +45 -0
- package/lib/logger/intercept-global-error.js +34 -25
- package/lib/logger/log-types.d.ts +4 -4
- package/lib/logger/log-types.js +1 -1
- package/lib/runtime/index.d.ts +1 -0
- package/lib/runtime/index.js +1 -0
- package/lib/runtime/react-devtools-hook.d.ts +19 -0
- package/lib/runtime/react-devtools-hook.js +20 -0
- package/lib/theme-layer.css +2 -1
- package/lib/utils/apiPath.d.ts +5 -0
- package/lib/utils/apiPath.js +5 -0
- package/lib/utils/axiosConfig.js +163 -9
- package/lib/utils/getAppId.d.ts +2 -4
- package/lib/utils/getAppId.js +2 -9
- package/lib/utils/getInitialInfo.d.ts +4 -3
- package/lib/utils/getInitialInfo.js +17 -8
- package/lib/utils/getUserProfile.js +4 -12
- package/lib/utils/hmr-api.d.ts +45 -0
- package/lib/utils/hmr-api.js +36 -0
- package/lib/utils/module-hot.d.ts +9 -5
- package/lib/utils/module-hot.js +9 -10
- package/lib/utils/postMessage.d.ts +0 -1
- package/lib/utils/postMessage.js +19 -6
- package/lib/utils/requestManager.js +1 -3
- package/lib/utils/resolveAppUrl.d.ts +27 -0
- package/lib/utils/resolveAppUrl.js +19 -0
- package/lib/utils/safeStringify.js +5 -0
- package/lib/utils/safeStringify.spec.d.ts +1 -0
- package/lib/utils/safeStringify.spec.js +125 -0
- package/lib/utils/scopedStorage.d.ts +5 -0
- package/lib/utils/scopedStorage.js +46 -0
- package/package.json +13 -6
- package/lib/apis/tools/generateImage.d.ts +0 -1
- package/lib/apis/tools/generateImage.js +0 -1
- package/lib/apis/tools/generateTextStream.d.ts +0 -1
- package/lib/apis/tools/generateTextStream.js +0 -1
- package/lib/components/theme/ui-config.d.ts +0 -1
- package/lib/components/theme/ui-config.js +0 -2
- package/lib/integrations/generateImage.d.ts +0 -1
- package/lib/integrations/generateImage.js +0 -47
- package/lib/integrations/generateTextStream.d.ts +0 -21
- package/lib/integrations/generateTextStream.js +0 -98
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { getAppId } from "../../utils/getAppId.js";
|
|
2
|
+
import { isNewPathEnabled } from "../../utils/apiPath.js";
|
|
2
3
|
const DEFAULT_CONFIG = {
|
|
3
|
-
getAppId: ()=>getAppId(
|
|
4
|
-
searchUserUrl: (appId)
|
|
5
|
-
listUsersUrl: (appId)
|
|
4
|
+
getAppId: ()=>getAppId(),
|
|
5
|
+
searchUserUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/search_user` : `/af/app/${appId}/runtime/api/v1/account/search_user`,
|
|
6
|
+
listUsersUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/list_users` : `/af/app/${appId}/runtime/api/v1/account/list_users`,
|
|
7
|
+
convertExternalContactUrl: (appId)=>isNewPathEnabled() ? `/app/${appId}/__runtime__/api/v1/account/convert_lark_user` : `/af/app/${appId}/runtime/api/v1/account/convert_lark_user`
|
|
6
8
|
};
|
|
7
9
|
class UserService {
|
|
8
10
|
config;
|
|
@@ -42,5 +44,23 @@ class UserService {
|
|
|
42
44
|
if (!response.ok) throw new Error('Failed to fetch users by ids');
|
|
43
45
|
return response.json();
|
|
44
46
|
}
|
|
47
|
+
async convertExternalContact(larkUserID) {
|
|
48
|
+
const appId = this.config.getAppId();
|
|
49
|
+
if (!appId) throw new Error('Failed to get appId');
|
|
50
|
+
const response = await fetch(this.config.convertExternalContactUrl(appId), {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json'
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
larkUserID
|
|
57
|
+
}),
|
|
58
|
+
credentials: 'include'
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) throw new Error('Failed to convert external contact');
|
|
61
|
+
const data = await response.json();
|
|
62
|
+
if (!data?.data?.userInfo?.userID) throw new Error('Invalid response from convert external contact');
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
45
65
|
}
|
|
46
66
|
export { UserService };
|
|
@@ -14,6 +14,8 @@ export type UserInfo = {
|
|
|
14
14
|
avatar: string;
|
|
15
15
|
userType: '_employee' | '_externalUser' | '_anonymousUser';
|
|
16
16
|
department: DepartmentBasic;
|
|
17
|
+
email?: string;
|
|
18
|
+
tenantName?: string;
|
|
17
19
|
};
|
|
18
20
|
export type DepartmentInfo = {
|
|
19
21
|
departmentID: string;
|
|
@@ -32,6 +34,7 @@ export type SearchUsersParams = {
|
|
|
32
34
|
query?: string;
|
|
33
35
|
offset?: number;
|
|
34
36
|
pageSize?: number;
|
|
37
|
+
searchExternalContact?: boolean;
|
|
35
38
|
};
|
|
36
39
|
export type SearchUsersResponse = {
|
|
37
40
|
data: {
|
|
@@ -40,6 +43,14 @@ export type SearchUsersResponse = {
|
|
|
40
43
|
};
|
|
41
44
|
status_code: string;
|
|
42
45
|
};
|
|
46
|
+
export type ConvertExternalContactResponse = {
|
|
47
|
+
data: {
|
|
48
|
+
userInfo: {
|
|
49
|
+
tenantID: number;
|
|
50
|
+
userID: number;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
};
|
|
43
54
|
export type BatchGetUsersResponse = {
|
|
44
55
|
data: {
|
|
45
56
|
userInfoMap: Record<string, UserInfo & SearchAvatar>;
|
|
@@ -61,6 +72,40 @@ export type SearchDepartmentsResponse = {
|
|
|
61
72
|
};
|
|
62
73
|
status_code: string;
|
|
63
74
|
};
|
|
75
|
+
export type ChatInfo = {
|
|
76
|
+
/** 群组 ID */
|
|
77
|
+
chatID: string;
|
|
78
|
+
/** 群组名称(国际化文本) */
|
|
79
|
+
name: I18nText;
|
|
80
|
+
/** 头像:URL 或 16 进制 RGB 颜色 */
|
|
81
|
+
avatar: string;
|
|
82
|
+
/** 是否是外部群 */
|
|
83
|
+
isExternal?: boolean;
|
|
84
|
+
/** 群成员数量(不包括机器人),搜索接口返回,批量查询接口不返回 */
|
|
85
|
+
userCount?: number;
|
|
86
|
+
};
|
|
87
|
+
export type SearchChatsParams = {
|
|
88
|
+
query?: string;
|
|
89
|
+
offset?: number;
|
|
90
|
+
pageSize?: number;
|
|
91
|
+
};
|
|
92
|
+
export type SearchChatsResponse = {
|
|
93
|
+
data: {
|
|
94
|
+
result: {
|
|
95
|
+
chatResult?: {
|
|
96
|
+
total: number;
|
|
97
|
+
items: ChatInfo[];
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
status_code: string;
|
|
102
|
+
};
|
|
103
|
+
export type BatchGetChatsResponse = {
|
|
104
|
+
data: {
|
|
105
|
+
chatInfoMap: Record<string, ChatInfo>;
|
|
106
|
+
};
|
|
107
|
+
status_code: string;
|
|
108
|
+
};
|
|
64
109
|
export type UserProfileAccountStatus = 0 | 1 | 2 | 3 | 4;
|
|
65
110
|
export type SimpleUserProfileInfo = {
|
|
66
111
|
name?: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { slardar } from "@lark-apaas/internal-slardar";
|
|
2
|
+
import { getHmrApi } from "../utils/hmr-api.js";
|
|
3
|
+
import { submitPostMessage } from "../utils/postMessage.js";
|
|
3
4
|
import { levelSchema } from "./log-types.js";
|
|
4
5
|
import { logger } from "./logger.js";
|
|
5
6
|
let devServerDisconnectInfo = null;
|
|
@@ -19,22 +20,26 @@ function processDevServerLog(log) {
|
|
|
19
20
|
status: 'disconnected'
|
|
20
21
|
}
|
|
21
22
|
});
|
|
22
|
-
|
|
23
|
+
slardar.sendEvent({
|
|
23
24
|
name: 'sandbox-devServer',
|
|
24
|
-
|
|
25
|
-
type: 'disconnected',
|
|
25
|
+
metrics: {
|
|
26
26
|
time
|
|
27
|
+
},
|
|
28
|
+
categories: {
|
|
29
|
+
type: 'disconnected'
|
|
27
30
|
}
|
|
28
31
|
});
|
|
29
32
|
return;
|
|
30
33
|
}
|
|
31
34
|
if (!devServerDisconnectInfo) return;
|
|
32
35
|
if (devFlag && log.includes('Trying to reconnect')) {
|
|
33
|
-
if (retryCount)
|
|
36
|
+
if (retryCount) slardar.sendEvent({
|
|
34
37
|
name: 'sandbox-devServer',
|
|
35
|
-
|
|
36
|
-
type: 'reconnect-failed',
|
|
38
|
+
metrics: {
|
|
37
39
|
retryCount: retryCount + 1
|
|
40
|
+
},
|
|
41
|
+
categories: {
|
|
42
|
+
type: 'reconnect-failed'
|
|
38
43
|
}
|
|
39
44
|
});
|
|
40
45
|
retryCount++;
|
|
@@ -52,37 +57,41 @@ function processDevServerLog(log) {
|
|
|
52
57
|
const startTime = devServerDisconnectInfo.time;
|
|
53
58
|
const duration = Date.now() - startTime;
|
|
54
59
|
devServerDisconnectInfo = null;
|
|
55
|
-
|
|
60
|
+
slardar.sendEvent({
|
|
56
61
|
name: 'sandbox-devServer',
|
|
57
|
-
|
|
58
|
-
type: 'devServer-reconnected',
|
|
62
|
+
metrics: {
|
|
59
63
|
startTime,
|
|
60
64
|
duration
|
|
65
|
+
},
|
|
66
|
+
categories: {
|
|
67
|
+
type: 'devServer-reconnected'
|
|
61
68
|
}
|
|
62
69
|
});
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
function listenModuleHmr() {
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
const hmr = getHmrApi();
|
|
74
|
+
if (hmr) {
|
|
75
|
+
hmr.onSuccess(()=>{
|
|
76
|
+
submitPostMessage({
|
|
77
|
+
type: 'DevServerMessage',
|
|
78
|
+
data: {
|
|
79
|
+
type: 'devServer-status',
|
|
80
|
+
status: 'hmr-apply-success'
|
|
81
|
+
}
|
|
82
|
+
});
|
|
74
83
|
});
|
|
75
|
-
|
|
76
|
-
console.warn('hmr apply failed',
|
|
77
|
-
|
|
84
|
+
hmr.onError((error)=>{
|
|
85
|
+
console.warn('hmr apply failed', error);
|
|
86
|
+
slardar.sendEvent({
|
|
78
87
|
name: 'sandbox-devServer',
|
|
79
88
|
categories: {
|
|
80
89
|
type: 'hmr-apply-failed',
|
|
81
|
-
|
|
90
|
+
error: String(error)
|
|
82
91
|
}
|
|
83
92
|
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
86
95
|
}
|
|
87
96
|
function interceptErrors() {
|
|
88
97
|
window.addEventListener('error', (event)=>{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import z from 'zod';
|
|
2
2
|
export declare const networkRequestLogSchema: z.ZodObject<{
|
|
3
3
|
method: z.ZodString;
|
|
4
|
-
status: z.
|
|
4
|
+
status: z.ZodNumber;
|
|
5
5
|
statusText: z.ZodString;
|
|
6
6
|
path: z.ZodString;
|
|
7
7
|
requestData: z.ZodOptional<z.ZodUnknown>;
|
|
@@ -27,11 +27,11 @@ export declare const logStackFrameSchema: z.ZodObject<{
|
|
|
27
27
|
columnNumber: z.ZodNumber;
|
|
28
28
|
}, z.core.$strip>;
|
|
29
29
|
export declare const levelSchema: z.ZodEnum<{
|
|
30
|
+
error: "error";
|
|
30
31
|
success: "success";
|
|
31
32
|
debug: "debug";
|
|
32
33
|
info: "info";
|
|
33
34
|
warn: "warn";
|
|
34
|
-
error: "error";
|
|
35
35
|
}>;
|
|
36
36
|
export declare const logMeta: z.ZodObject<{
|
|
37
37
|
stacktrace: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -52,11 +52,11 @@ export declare const logMeta: z.ZodObject<{
|
|
|
52
52
|
export declare const selectedLogSchema: z.ZodObject<{
|
|
53
53
|
type: z.ZodLiteral<"typedLogV2">;
|
|
54
54
|
level: z.ZodEnum<{
|
|
55
|
+
error: "error";
|
|
55
56
|
success: "success";
|
|
56
57
|
debug: "debug";
|
|
57
58
|
info: "info";
|
|
58
59
|
warn: "warn";
|
|
59
|
-
error: "error";
|
|
60
60
|
}>;
|
|
61
61
|
id: z.ZodString;
|
|
62
62
|
args: z.ZodArray<z.ZodUnknown>;
|
|
@@ -80,11 +80,11 @@ export declare const selectedLogSchema: z.ZodObject<{
|
|
|
80
80
|
export type LogLevel = z.infer<typeof levelSchema>;
|
|
81
81
|
export declare const logWithMetaSchema: z.ZodObject<{
|
|
82
82
|
level: z.ZodEnum<{
|
|
83
|
+
error: "error";
|
|
83
84
|
success: "success";
|
|
84
85
|
debug: "debug";
|
|
85
86
|
info: "info";
|
|
86
87
|
warn: "warn";
|
|
87
|
-
error: "error";
|
|
88
88
|
}>;
|
|
89
89
|
args: z.ZodArray<z.ZodUnknown>;
|
|
90
90
|
meta: z.ZodOptional<z.ZodObject<{
|
package/lib/logger/log-types.js
CHANGED
package/lib/runtime/index.d.ts
CHANGED
package/lib/runtime/index.js
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inject minimal __REACT_DEVTOOLS_GLOBAL_HOOK__ before React loads.
|
|
3
|
+
* React checks for this hook during module initialization and registers its
|
|
4
|
+
* renderer via hook.inject(). This gives us access to renderer.overrideProps()
|
|
5
|
+
* for live component prop modification in the inspector.
|
|
6
|
+
*
|
|
7
|
+
* Must execute before React's module-level code runs.
|
|
8
|
+
*
|
|
9
|
+
* When react-refresh-runtime runs first (as an rspack runtime module),
|
|
10
|
+
* it may create __REACT_DEVTOOLS_GLOBAL_HOOK__ with an inject() that
|
|
11
|
+
* doesn't populate the renderers Map. We patch the existing hook to
|
|
12
|
+
* ensure renderers are always tracked.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
__REACT_DEVTOOLS_GLOBAL_HOOK__?: any;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
if ('undefined' != typeof window && 'production' !== process.env.NODE_ENV) if (window.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
|
|
2
|
+
const hook = window.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
3
|
+
if (!(hook.renderers instanceof Map)) hook.renderers = new Map();
|
|
4
|
+
const originalInject = 'function' == typeof hook.inject ? hook.inject.bind(hook) : null;
|
|
5
|
+
hook.inject = function(renderer) {
|
|
6
|
+
const id = originalInject ? originalInject(renderer) : hook.renderers.size + 1;
|
|
7
|
+
if (null != id && !hook.renderers.has(id)) hook.renderers.set(id, renderer);
|
|
8
|
+
return id;
|
|
9
|
+
};
|
|
10
|
+
} else window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
11
|
+
renderers: new Map(),
|
|
12
|
+
supportsFiber: true,
|
|
13
|
+
inject (renderer) {
|
|
14
|
+
const id = this.renderers.size + 1;
|
|
15
|
+
this.renderers.set(id, renderer);
|
|
16
|
+
return id;
|
|
17
|
+
},
|
|
18
|
+
onCommitFiberRoot () {},
|
|
19
|
+
onCommitFiberUnmount () {}
|
|
20
|
+
};
|
package/lib/theme-layer.css
CHANGED
package/lib/utils/axiosConfig.js
CHANGED
|
@@ -3,6 +3,93 @@ import { observable } from "@lark-apaas/observable-web";
|
|
|
3
3
|
import { logger } from "../apis/logger.js";
|
|
4
4
|
import { getStacktrace } from "../logger/selected-logs.js";
|
|
5
5
|
import { safeStringify } from "./safeStringify.js";
|
|
6
|
+
import { slardar } from "@lark-apaas/internal-slardar";
|
|
7
|
+
import { normalizeBasePath } from "./utils.js";
|
|
8
|
+
const APP_CLIENT_API_LOG_TYPE = 'app_client_api_log';
|
|
9
|
+
function stripBasePath(urlPath) {
|
|
10
|
+
const base = normalizeBasePath(process.env.CLIENT_BASE_PATH);
|
|
11
|
+
if (base && urlPath.startsWith(base)) return urlPath.slice(base.length) || '/';
|
|
12
|
+
return urlPath;
|
|
13
|
+
}
|
|
14
|
+
let _pageRoutes = null;
|
|
15
|
+
function getPageRouteDefinitions() {
|
|
16
|
+
if (_pageRoutes) return _pageRoutes;
|
|
17
|
+
try {
|
|
18
|
+
const raw = process.env.__PAGE_ROUTE_DEFINITIONS__;
|
|
19
|
+
if (raw) {
|
|
20
|
+
const parsed = JSON.parse(raw);
|
|
21
|
+
if (Array.isArray(parsed)) {
|
|
22
|
+
_pageRoutes = parsed;
|
|
23
|
+
return _pageRoutes;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
} catch {}
|
|
27
|
+
_pageRoutes = [];
|
|
28
|
+
return _pageRoutes;
|
|
29
|
+
}
|
|
30
|
+
let _apiRoutes = null;
|
|
31
|
+
function getApiRouteDefinitions() {
|
|
32
|
+
if (_apiRoutes) return _apiRoutes;
|
|
33
|
+
try {
|
|
34
|
+
const raw = process.env.__API_ROUTE_DEFINITIONS__;
|
|
35
|
+
if (raw) {
|
|
36
|
+
const parsed = JSON.parse(raw);
|
|
37
|
+
if (Array.isArray(parsed)) {
|
|
38
|
+
_apiRoutes = parsed;
|
|
39
|
+
return _apiRoutes;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
} catch {}
|
|
43
|
+
_apiRoutes = [];
|
|
44
|
+
return _apiRoutes;
|
|
45
|
+
}
|
|
46
|
+
function matchRoute(concretePath, routes) {
|
|
47
|
+
const segments = concretePath.split('/').filter(Boolean);
|
|
48
|
+
for (const route of routes){
|
|
49
|
+
const routeSegments = route.path.split('/').filter(Boolean);
|
|
50
|
+
if (routeSegments.length !== segments.length) continue;
|
|
51
|
+
let match = true;
|
|
52
|
+
for(let i = 0; i < routeSegments.length; i++)if (!routeSegments[i].startsWith(':')) {
|
|
53
|
+
if (routeSegments[i] !== segments[i]) {
|
|
54
|
+
match = false;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (match) return route.path;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
function matchApiRoute(method, concretePath) {
|
|
63
|
+
const routes = getApiRouteDefinitions();
|
|
64
|
+
const segments = concretePath.split('/').filter(Boolean);
|
|
65
|
+
for (const route of routes){
|
|
66
|
+
if ('*' !== route.method && route.method !== method) continue;
|
|
67
|
+
const routeSegments = route.path.split('/').filter(Boolean);
|
|
68
|
+
if (routeSegments.length !== segments.length) continue;
|
|
69
|
+
let match = true;
|
|
70
|
+
for(let i = 0; i < routeSegments.length; i++)if (!routeSegments[i].startsWith(':')) {
|
|
71
|
+
if (routeSegments[i] !== segments[i]) {
|
|
72
|
+
match = false;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (match) return route.path;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
function getRefererPath() {
|
|
81
|
+
try {
|
|
82
|
+
if ('undefined' == typeof window || !window.location?.pathname) return '/';
|
|
83
|
+
const rawPath = stripBasePath(window.location.pathname);
|
|
84
|
+
return matchRoute(rawPath, getPageRouteDefinitions()) || rawPath;
|
|
85
|
+
} catch {
|
|
86
|
+
return '/';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function getApiField(method, path) {
|
|
90
|
+
const matched = matchApiRoute(method, path);
|
|
91
|
+
return `${method} ${matched || path}`;
|
|
92
|
+
}
|
|
6
93
|
const isValidResponse = (resp)=>null != resp && 'object' == typeof resp && 'config' in resp && null !== resp.config && void 0 !== resp.config && 'object' == typeof resp.config && 'status' in resp && 'number' == typeof resp.status && 'data' in resp;
|
|
7
94
|
async function logResponse(ok, responseOrError) {
|
|
8
95
|
if (isValidResponse(responseOrError)) {
|
|
@@ -54,7 +141,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
54
141
|
logTraceID
|
|
55
142
|
};
|
|
56
143
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
57
|
-
logger.
|
|
144
|
+
logger.log({
|
|
58
145
|
level: ok,
|
|
59
146
|
args: [
|
|
60
147
|
parts.join(''),
|
|
@@ -110,7 +197,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
110
197
|
const stacktrace = await requestStacktraceMap.get(requestUUID);
|
|
111
198
|
const logMeta = {};
|
|
112
199
|
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
113
|
-
logger.
|
|
200
|
+
logger.log({
|
|
114
201
|
level: 'error',
|
|
115
202
|
args: [
|
|
116
203
|
parts.join(''),
|
|
@@ -120,7 +207,7 @@ async function logResponse(ok, responseOrError) {
|
|
|
120
207
|
});
|
|
121
208
|
return;
|
|
122
209
|
}
|
|
123
|
-
logger.
|
|
210
|
+
logger.log({
|
|
124
211
|
level: 'error',
|
|
125
212
|
args: [
|
|
126
213
|
'请求失败:无响应对象或配置信息'
|
|
@@ -138,13 +225,20 @@ function handleSpanEnd(cfg, response, error) {
|
|
|
138
225
|
const errorMessage = error?.message || '未知错误';
|
|
139
226
|
const url = response?.request?.responseURL || errorResponse?.request?.responseURL || cfg.url || "";
|
|
140
227
|
const method = (cfg.method || 'GET').toUpperCase();
|
|
141
|
-
const
|
|
228
|
+
const rawPath = url.split('?')[0].replace(/^https?:\/\/[^/]+/, '') || '/';
|
|
229
|
+
const path = stripBasePath(rawPath);
|
|
230
|
+
const durationMs = startTime ? Date.now() - startTime : void 0;
|
|
231
|
+
const referer_path = getRefererPath();
|
|
232
|
+
const api = getApiField(method, path);
|
|
233
|
+
const type = APP_CLIENT_API_LOG_TYPE;
|
|
142
234
|
const logData = {
|
|
143
235
|
method,
|
|
144
236
|
path,
|
|
145
237
|
url,
|
|
146
|
-
duration_ms:
|
|
147
|
-
status: response ? response.status : errorResponse.status || 0
|
|
238
|
+
duration_ms: durationMs,
|
|
239
|
+
status: response ? response.status : errorResponse.status || 0,
|
|
240
|
+
referer_path,
|
|
241
|
+
type
|
|
148
242
|
};
|
|
149
243
|
if (error) logData.error_message = errorMessage;
|
|
150
244
|
if ('undefined' != typeof navigator) logData.user_agent = navigator.userAgent;
|
|
@@ -157,7 +251,19 @@ function handleSpanEnd(cfg, response, error) {
|
|
|
157
251
|
const responseData = response?.data || errorResponse?.data;
|
|
158
252
|
if (responseData) logData.response = responseData;
|
|
159
253
|
const level = error ? 'ERROR' : 'INFO';
|
|
160
|
-
observable.log(level, safeStringify(logData), {
|
|
254
|
+
observable.log(level, safeStringify(logData), {
|
|
255
|
+
referer_path,
|
|
256
|
+
api,
|
|
257
|
+
type,
|
|
258
|
+
duration_ms: durationMs
|
|
259
|
+
}, currentSpan);
|
|
260
|
+
if ('function' == typeof currentSpan.setAttributes) currentSpan.setAttributes({
|
|
261
|
+
referer_path,
|
|
262
|
+
api,
|
|
263
|
+
duration_ms: durationMs,
|
|
264
|
+
module: 'app_web',
|
|
265
|
+
source_type: 'platform'
|
|
266
|
+
});
|
|
161
267
|
'function' == typeof currentSpan.end && currentSpan.end();
|
|
162
268
|
} catch (e) {
|
|
163
269
|
console.error('[AxiosTrace] Log span failed:', e);
|
|
@@ -193,6 +299,10 @@ AxiosProto.request = function(configOrUrl, config) {
|
|
|
193
299
|
return response;
|
|
194
300
|
}, (error)=>{
|
|
195
301
|
handleSpanEnd(error.config || finalConfig, null, error);
|
|
302
|
+
slardar.captureException(error, {
|
|
303
|
+
source: 'toolkit',
|
|
304
|
+
module: 'axios-request'
|
|
305
|
+
});
|
|
196
306
|
throw error;
|
|
197
307
|
});
|
|
198
308
|
};
|
|
@@ -234,6 +344,12 @@ function initAxiosConfig(axiosInstance) {
|
|
|
234
344
|
config._startTime = config._startTime || Date.now();
|
|
235
345
|
const csrfToken = window.csrfToken;
|
|
236
346
|
if (csrfToken) config.headers['X-Suda-Csrf-Token'] = csrfToken;
|
|
347
|
+
if ('undefined' != typeof window && window.location?.pathname) config.headers['X-Page-Route'] = window.location.pathname;
|
|
348
|
+
const refererPath = getRefererPath();
|
|
349
|
+
config.headers['Rpc-Persist-Apaas-Observability-Referer-Path'] = refererPath;
|
|
350
|
+
const reqMethod = (config.method || 'GET').toUpperCase();
|
|
351
|
+
const requestPath = stripBasePath((config.url || '').split('?')[0]);
|
|
352
|
+
config.headers['Rpc-Persist-Apaas-Observability-Api'] = getApiField(reqMethod, requestPath);
|
|
237
353
|
return config;
|
|
238
354
|
}, (error)=>Promise.reject(error));
|
|
239
355
|
instance.interceptors.response.use((response)=>response, (error)=>{
|
|
@@ -241,8 +357,8 @@ function initAxiosConfig(axiosInstance) {
|
|
|
241
357
|
if (error.response?.status === 403) {
|
|
242
358
|
const method = (error.config?.method || 'GET').toUpperCase();
|
|
243
359
|
const url = (error.config?.url || '').split('?')[0];
|
|
244
|
-
logger.
|
|
245
|
-
level: '
|
|
360
|
+
logger.log({
|
|
361
|
+
level: 'warn',
|
|
246
362
|
args: [
|
|
247
363
|
`请求被拒绝(403):${method} ${url}`,
|
|
248
364
|
{
|
|
@@ -252,9 +368,47 @@ function initAxiosConfig(axiosInstance) {
|
|
|
252
368
|
],
|
|
253
369
|
meta: {}
|
|
254
370
|
});
|
|
371
|
+
slardar.sendEvent({
|
|
372
|
+
name: 'toolkit_axios_403_downgrade',
|
|
373
|
+
categories: {
|
|
374
|
+
url: String(error.config?.url || ''),
|
|
375
|
+
method: String(error.config?.method || ''),
|
|
376
|
+
...'production' !== process.env.NODE_ENV && {
|
|
377
|
+
responseData: (()=>{
|
|
378
|
+
try {
|
|
379
|
+
const data = error.response?.data;
|
|
380
|
+
if (!data) return '';
|
|
381
|
+
return 'string' == typeof data ? data.slice(0, 512) : JSON.stringify(data).slice(0, 512);
|
|
382
|
+
} catch {
|
|
383
|
+
return '';
|
|
384
|
+
}
|
|
385
|
+
})()
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
});
|
|
255
389
|
return error.response;
|
|
256
390
|
}
|
|
257
391
|
} catch (e) {}
|
|
392
|
+
slardar.sendEvent({
|
|
393
|
+
name: 'toolkit_axios_response_error',
|
|
394
|
+
categories: {
|
|
395
|
+
url: String(error.config?.url || ''),
|
|
396
|
+
method: String(error.config?.method || ''),
|
|
397
|
+
status: String(error.response?.status || ''),
|
|
398
|
+
...'production' !== process.env.NODE_ENV && {
|
|
399
|
+
errorMessage: String(error.message || ''),
|
|
400
|
+
responseData: (()=>{
|
|
401
|
+
try {
|
|
402
|
+
const data = error.response?.data;
|
|
403
|
+
if (!data) return '';
|
|
404
|
+
return 'string' == typeof data ? data.slice(0, 512) : JSON.stringify(data).slice(0, 512);
|
|
405
|
+
} catch {
|
|
406
|
+
return '';
|
|
407
|
+
}
|
|
408
|
+
})()
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
});
|
|
258
412
|
return Promise.reject(error);
|
|
259
413
|
});
|
|
260
414
|
'production' !== process.env.NODE_ENV && instance.interceptors.response.use((response)=>{
|
package/lib/utils/getAppId.d.ts
CHANGED
package/lib/utils/getAppId.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
function getAppId(
|
|
2
|
-
if (window.MIAODA_APP_ID) return window.MIAODA_APP_ID;
|
|
3
|
-
let prefix;
|
|
4
|
-
prefix = path.includes('/ai/feida/runtime/') ? '/ai/feida/runtime/' : path.includes('/spark/r/') ? '/spark/r/' : '/ai/miaoda/';
|
|
1
|
+
function getAppId() {
|
|
5
2
|
const windowAppId = window.appId || null;
|
|
6
|
-
|
|
7
|
-
const remainder = path.substring(prefix.length);
|
|
8
|
-
const nextSlashIndex = remainder.indexOf('/');
|
|
9
|
-
if (-1 === nextSlashIndex) return remainder || windowAppId;
|
|
10
|
-
return remainder.substring(0, nextSlashIndex) || windowAppId;
|
|
3
|
+
return windowAppId;
|
|
11
4
|
}
|
|
12
5
|
export { getAppId };
|
|
@@ -13,9 +13,10 @@ interface AppRuntimePublished {
|
|
|
13
13
|
interface BucketConfig {
|
|
14
14
|
default_bucket_id?: string;
|
|
15
15
|
}
|
|
16
|
-
|
|
17
|
-
export declare function getInitialInfo(refresh?: boolean): Promise<{
|
|
16
|
+
declare let initialInfo: {
|
|
18
17
|
app_info?: AppRuntimePublished;
|
|
19
18
|
app_runtime_extra?: AppRuntimeExtra;
|
|
20
|
-
}
|
|
19
|
+
} | undefined;
|
|
20
|
+
/** 获取应用初始化信息(仅全栈沙箱模式下使用) */
|
|
21
|
+
export declare function getInitialInfo(refresh?: boolean): Promise<typeof initialInfo>;
|
|
21
22
|
export {};
|