@lark-apaas/client-toolkit 1.2.17-alpha.13 → 1.2.17-alpha.14

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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 监听路由变化,更新当前匹配的参数化路由模式
3
+ * 供观测 SDK 获取 referer_path 字段
4
+ */
5
+ export default function RoutePatternTracker(): any;
@@ -0,0 +1,13 @@
1
+ import { useEffect } from "react";
2
+ import { useLocation } from "react-router-dom";
3
+ import { updateRoutePattern } from "../../utils/routePattern.js";
4
+ function RoutePatternTracker() {
5
+ const location = useLocation();
6
+ useEffect(()=>{
7
+ updateRoutePattern(location.pathname);
8
+ }, [
9
+ location.pathname
10
+ ]);
11
+ return null;
12
+ }
13
+ export { RoutePatternTracker as default };
@@ -4,6 +4,7 @@ import { ConfigProvider } from "antd";
4
4
  import { MiaodaInspector } from "@lark-apaas/miaoda-inspector";
5
5
  import zh_CN from "antd/locale/zh_CN";
6
6
  import IframeBridge from "./IframeBridge.js";
7
+ import RoutePatternTracker from "./RoutePatternTracker.js";
7
8
  import { Toaster } from "./sonner.js";
8
9
  import { PageHoc } from "./PageHoc.js";
9
10
  import { reportTeaEvent } from "./utils/tea.js";
@@ -60,6 +61,7 @@ const App = (props)=>{
60
61
  !disableToaster && true !== appFlags.customToaster && /*#__PURE__*/ jsx(Toaster, {}),
61
62
  'production' !== process.env.NODE_ENV && /*#__PURE__*/ jsx(MiaodaInspector, {}),
62
63
  'production' !== process.env.NODE_ENV && /*#__PURE__*/ jsx(IframeBridge, {}),
64
+ /*#__PURE__*/ jsx(RoutePatternTracker, {}),
63
65
  /*#__PURE__*/ jsx(PageHoc, {
64
66
  children: props.children
65
67
  })
@@ -1,20 +1,6 @@
1
1
  import { normalizeBasePath } from "../../../utils/utils.js";
2
2
  import { api_delete, api_get, api_head, api_options, api_patch, api_post, api_put } from "./api-panel.js";
3
- async function getRoutes() {
4
- let routes = [
5
- {
6
- path: '/'
7
- }
8
- ];
9
- try {
10
- const basePath = normalizeBasePath(process.env.CLIENT_BASE_PATH);
11
- const res = await fetch(`${basePath}/routes.json`);
12
- routes = await res.json();
13
- } catch (error) {
14
- console.warn('get routes.json error', error);
15
- }
16
- return routes;
17
- }
3
+ import { getRouteDefinitions } from "../../../utils/routePattern.js";
18
4
  async function getSourceMap() {
19
5
  if ('vite' === process.env.BUILD_TOOL) return '';
20
6
  let sourceMapContent = '';
@@ -28,7 +14,7 @@ async function getSourceMap() {
28
14
  return sourceMapContent;
29
15
  }
30
16
  const childApi = {
31
- getRoutes,
17
+ getRoutes: getRouteDefinitions,
32
18
  updateAppInfo: (appInfo)=>{
33
19
  dispatchEvent(new CustomEvent('MiaoDaMetaInfoChanged', {
34
20
  detail: appInfo
@@ -4,6 +4,26 @@ import { logger } from "../apis/logger.js";
4
4
  import { getStacktrace } from "../logger/selected-logs.js";
5
5
  import { safeStringify } from "./safeStringify.js";
6
6
  import { slardar } from "@lark-apaas/internal-slardar";
7
+ import { getCurrentRoutePattern } from "./routePattern.js";
8
+ import { normalizeBasePath } from "./utils.js";
9
+ const APP_CLIENT_API_LOG_TYPE = 'app_client_api_log';
10
+ function getRefererPath() {
11
+ try {
12
+ return getCurrentRoutePattern();
13
+ } catch {
14
+ return '/';
15
+ }
16
+ }
17
+ function getApiField(method, response, errorResponse, fallbackPath) {
18
+ const matchRoute = response?.headers?.['x-match-route'] || errorResponse?.headers?.['x-match-route'] || '';
19
+ const routePath = matchRoute || fallbackPath;
20
+ return `${method} ${routePath}`;
21
+ }
22
+ function stripBasePath(path) {
23
+ const base = normalizeBasePath(process.env.CLIENT_BASE_PATH);
24
+ if (base && path.startsWith(base)) return path.slice(base.length) || '/';
25
+ return path;
26
+ }
7
27
  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;
8
28
  async function logResponse(ok, responseOrError) {
9
29
  if (isValidResponse(responseOrError)) {
@@ -139,13 +159,20 @@ function handleSpanEnd(cfg, response, error) {
139
159
  const errorMessage = error?.message || '未知错误';
140
160
  const url = response?.request?.responseURL || errorResponse?.request?.responseURL || cfg.url || "";
141
161
  const method = (cfg.method || 'GET').toUpperCase();
142
- const path = url.split('?')[0].replace(/^https?:\/\/[^/]+/, '') || '/';
162
+ const rawPath = url.split('?')[0].replace(/^https?:\/\/[^/]+/, '') || '/';
163
+ const path = stripBasePath(rawPath);
164
+ const durationMs = startTime ? Date.now() - startTime : void 0;
165
+ const referer_path = getRefererPath();
166
+ const api = getApiField(method, response, errorResponse, path);
167
+ const type = APP_CLIENT_API_LOG_TYPE;
143
168
  const logData = {
144
169
  method,
145
170
  path,
146
171
  url,
147
- duration_ms: startTime ? Date.now() - startTime : void 0,
148
- status: response ? response.status : errorResponse.status || 0
172
+ duration_ms: durationMs,
173
+ status: response ? response.status : errorResponse.status || 0,
174
+ referer_path,
175
+ type
149
176
  };
150
177
  if (error) logData.error_message = errorMessage;
151
178
  if ('undefined' != typeof navigator) logData.user_agent = navigator.userAgent;
@@ -158,7 +185,12 @@ function handleSpanEnd(cfg, response, error) {
158
185
  const responseData = response?.data || errorResponse?.data;
159
186
  if (responseData) logData.response = responseData;
160
187
  const level = error ? 'ERROR' : 'INFO';
161
- observable.log(level, safeStringify(logData), {}, currentSpan);
188
+ observable.log(level, safeStringify(logData), {
189
+ referer_path,
190
+ api,
191
+ type,
192
+ duration_ms: durationMs
193
+ }, currentSpan);
162
194
  'function' == typeof currentSpan.end && currentSpan.end();
163
195
  } catch (e) {
164
196
  console.error('[AxiosTrace] Log span failed:', e);
@@ -0,0 +1,13 @@
1
+ export declare function getRouteDefinitions(): Promise<{
2
+ path: string;
3
+ }[]>;
4
+ /**
5
+ * 根据当前 pathname 匹配路由模式并更新存储
6
+ * 使用 react-router 的 matchPath 确保匹配逻辑与路由一致
7
+ */
8
+ export declare function updateRoutePattern(pathname: string): Promise<void>;
9
+ /**
10
+ * 获取当前匹配的参数化路由模式
11
+ * 供 axiosConfig 等非 React 上下文使用
12
+ */
13
+ export declare function getCurrentRoutePattern(): string;
@@ -0,0 +1,63 @@
1
+ import { matchPath } from "react-router-dom";
2
+ import { normalizeBasePath } from "./utils.js";
3
+ let currentRoutePattern = '/';
4
+ let routeDefinitions = null;
5
+ function getInjectedRouteDefinitions() {
6
+ try {
7
+ const raw = process.env.__ROUTE_DEFINITIONS__;
8
+ if (raw) {
9
+ const parsed = JSON.parse(raw);
10
+ if (Array.isArray(parsed) && parsed.length > 0) return parsed;
11
+ }
12
+ } catch {}
13
+ return null;
14
+ }
15
+ async function loadRouteDefinitions() {
16
+ if (routeDefinitions) return routeDefinitions;
17
+ const injected = getInjectedRouteDefinitions();
18
+ if (injected) {
19
+ routeDefinitions = injected;
20
+ return routeDefinitions;
21
+ }
22
+ try {
23
+ const basePath = normalizeBasePath(process.env.CLIENT_BASE_PATH);
24
+ const res = await fetch(`${basePath}/routes.json`);
25
+ routeDefinitions = await res.json();
26
+ } catch {
27
+ routeDefinitions = [
28
+ {
29
+ path: '/'
30
+ }
31
+ ];
32
+ }
33
+ return routeDefinitions;
34
+ }
35
+ async function getRouteDefinitions() {
36
+ return loadRouteDefinitions();
37
+ }
38
+ async function updateRoutePattern(pathname) {
39
+ const routes = await loadRouteDefinitions();
40
+ const basePath = normalizeBasePath(process.env.CLIENT_BASE_PATH);
41
+ let relativePath = pathname;
42
+ if (basePath && pathname.startsWith(basePath)) relativePath = pathname.slice(basePath.length) || '/';
43
+ const sortedRoutes = [
44
+ ...routes
45
+ ].sort((a, b)=>b.path.length - a.path.length);
46
+ for (const route of sortedRoutes){
47
+ let routePath = route.path;
48
+ if (basePath && routePath.startsWith(basePath)) routePath = routePath.slice(basePath.length) || '/';
49
+ const match = matchPath({
50
+ path: routePath,
51
+ end: true
52
+ }, relativePath);
53
+ if (match) {
54
+ currentRoutePattern = routePath;
55
+ return;
56
+ }
57
+ }
58
+ currentRoutePattern = relativePath;
59
+ }
60
+ function getCurrentRoutePattern() {
61
+ return currentRoutePattern;
62
+ }
63
+ export { getCurrentRoutePattern, getRouteDefinitions, updateRoutePattern };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/client-toolkit",
3
- "version": "1.2.17-alpha.13",
3
+ "version": "1.2.17-alpha.14",
4
4
  "types": "./lib/index.d.ts",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -99,7 +99,7 @@
99
99
  "@ant-design/colors": "^7.2.1",
100
100
  "@ant-design/cssinjs": "^1.24.0",
101
101
  "@data-loom/js": "0.4.9",
102
- "@lark-apaas/aily-web-sdk": "0.0.2-alpha.15",
102
+ "@lark-apaas/aily-web-sdk": "^0.0.6",
103
103
  "@lark-apaas/auth-sdk": "^0.1.1",
104
104
  "@lark-apaas/client-capability": "^0.1.5",
105
105
  "@lark-apaas/internal-slardar": ">=0.0.1",