@lark-apaas/client-toolkit 1.1.21-alpha.auth.dev.1 → 1.1.21-alpha.auth.dev.10
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/README.md +68 -0
- package/lib/antd-table.d.ts +4 -0
- package/lib/antd-table.js +2 -0
- package/lib/apis/utils/getAxiosForBackend.d.ts +1 -0
- package/lib/apis/utils/getAxiosForBackend.js +1 -0
- package/lib/auth.d.ts +1 -0
- package/lib/auth.js +2 -0
- package/lib/components/AppContainer/index.js +179 -8
- package/lib/components/AppContainer/safety.js +16 -16
- package/lib/components/AppContainer/utils/getLarkUser.d.ts +1 -0
- package/lib/components/AppContainer/utils/getLarkUser.js +17 -0
- package/lib/components/AppContainer/utils/tea.d.ts +8 -0
- package/lib/components/AppContainer/utils/tea.js +51 -0
- package/lib/components/ErrorRender/index.js +17 -10
- package/lib/components/User/UserDisplay.d.ts +3 -2
- package/lib/components/User/UserDisplay.js +24 -23
- package/lib/components/User/index.d.ts +1 -1
- package/lib/components/ui/badge.d.ts +1 -1
- package/lib/components/ui/button.d.ts +1 -1
- package/lib/hooks/useCurrentUserProfile.js +4 -4
- package/lib/logger/selected-logs.js +11 -3
- package/lib/server-log/index.d.ts +9 -0
- package/lib/server-log/index.js +2 -0
- package/lib/server-log/poller.d.ts +87 -0
- package/lib/server-log/poller.js +135 -0
- package/lib/server-log/types.d.ts +166 -0
- package/lib/server-log/types.js +0 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/tea.d.ts +7 -0
- package/lib/types/tea.js +5 -0
- package/lib/utils/axiosConfig.js +118 -48
- package/lib/utils/deviceType.d.ts +3 -0
- package/lib/utils/deviceType.js +13 -0
- package/lib/utils/getAxiosForBackend.d.ts +11 -0
- package/lib/utils/getAxiosForBackend.js +21 -0
- package/lib/utils/getParentOrigin.d.ts +2 -1
- package/lib/utils/getParentOrigin.js +8 -1
- package/lib/utils/requestManager.d.ts +2 -0
- package/lib/utils/requestManager.js +26 -0
- package/lib/utils/userProfileCache.d.ts +12 -0
- package/lib/utils/userProfileCache.js +26 -0
- package/package.json +22 -6
package/lib/utils/axiosConfig.js
CHANGED
|
@@ -1,59 +1,129 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { logger } from "../apis/logger.js";
|
|
3
3
|
import { getStacktrace } from "../logger/selected-logs.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
4
|
+
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;
|
|
5
|
+
async function logResponse(ok, responseOrError) {
|
|
6
|
+
if (isValidResponse(responseOrError)) {
|
|
7
|
+
const response = responseOrError;
|
|
8
|
+
const okToTextMap = {
|
|
9
|
+
success: '请求成功:',
|
|
10
|
+
error: '请求失败:'
|
|
11
|
+
};
|
|
12
|
+
const realOK = 'success' === ok && response.status >= 200 && response.status < 300;
|
|
13
|
+
const method = (response.config.method || 'GET').toUpperCase();
|
|
14
|
+
const parts = [
|
|
15
|
+
okToTextMap[realOK ? 'success' : 'error'],
|
|
16
|
+
method,
|
|
17
|
+
' ',
|
|
18
|
+
(response.config.url || '').split('?')[0].replace(/^\/spark\/p\/app_\w+/, ''),
|
|
19
|
+
' - ',
|
|
20
|
+
Date.now() - response.config._startTime,
|
|
21
|
+
'ms'
|
|
22
|
+
];
|
|
23
|
+
const logTraceID = response.headers?.['x-log-trace-id'];
|
|
24
|
+
const queryParams = {};
|
|
25
|
+
const url = response.config.url || '';
|
|
26
|
+
const queryString = url.split('?')[1];
|
|
27
|
+
if (queryString) {
|
|
28
|
+
const urlParams = new URLSearchParams(queryString);
|
|
29
|
+
urlParams.forEach((value, key)=>{
|
|
30
|
+
queryParams[key] = value;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (response.config.params) Object.assign(queryParams, response.config.params);
|
|
34
|
+
const args = [
|
|
35
|
+
{
|
|
36
|
+
请求参数: response.config.data,
|
|
37
|
+
...Object.keys(queryParams).length > 0 && {
|
|
38
|
+
查询参数: queryParams
|
|
39
|
+
},
|
|
40
|
+
返回数据: response.data,
|
|
41
|
+
请求摘要: {
|
|
42
|
+
方法: method,
|
|
43
|
+
TraceID: logTraceID,
|
|
44
|
+
状态: `${response.statusText}[状态码${response.status}]`,
|
|
45
|
+
时间: `${new Date().toLocaleString()}`
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
const requestUUID = response.config._requestUUID;
|
|
50
|
+
const stacktrace = await requestStacktraceMap.get(requestUUID);
|
|
51
|
+
const logMeta = {
|
|
52
|
+
logTraceID
|
|
53
|
+
};
|
|
54
|
+
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
55
|
+
logger.log({
|
|
56
|
+
level: ok,
|
|
57
|
+
args: [
|
|
58
|
+
parts.join(''),
|
|
59
|
+
...args
|
|
60
|
+
],
|
|
61
|
+
meta: logMeta
|
|
25
62
|
});
|
|
63
|
+
return;
|
|
26
64
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
65
|
+
const error = responseOrError;
|
|
66
|
+
if (error && error.config && 'object' == typeof error.config) {
|
|
67
|
+
const errorType = error.code || 'UNKNOWN_ERROR';
|
|
68
|
+
const errorMessage = error.message || '未知错误';
|
|
69
|
+
const method = (error.config.method || 'GET').toUpperCase();
|
|
70
|
+
const url = error.config.url || '';
|
|
71
|
+
const startTime = error.config._startTime;
|
|
72
|
+
const duration = startTime ? Date.now() - startTime : 0;
|
|
73
|
+
const parts = [
|
|
74
|
+
'网络请求失败:',
|
|
75
|
+
method,
|
|
76
|
+
' ',
|
|
77
|
+
url.split('?')[0].replace(/^\/spark\/p\/app_\w+/, ''),
|
|
78
|
+
' - ',
|
|
79
|
+
errorType,
|
|
80
|
+
duration > 0 ? ` (${duration}ms)` : ''
|
|
81
|
+
];
|
|
82
|
+
const queryParams = {};
|
|
83
|
+
const queryString = url.split('?')[1];
|
|
84
|
+
if (queryString) {
|
|
85
|
+
const urlParams = new URLSearchParams(queryString);
|
|
86
|
+
urlParams.forEach((value, key)=>{
|
|
87
|
+
queryParams[key] = value;
|
|
88
|
+
});
|
|
40
89
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
90
|
+
if (error.config.params) Object.assign(queryParams, error.config.params);
|
|
91
|
+
const args = [
|
|
92
|
+
{
|
|
93
|
+
请求参数: error.config.data,
|
|
94
|
+
...Object.keys(queryParams).length > 0 && {
|
|
95
|
+
查询参数: queryParams
|
|
96
|
+
},
|
|
97
|
+
错误信息: errorMessage,
|
|
98
|
+
请求摘要: {
|
|
99
|
+
方法: method,
|
|
100
|
+
错误类型: errorType,
|
|
101
|
+
错误代码: error.code,
|
|
102
|
+
超时设置: error.config.timeout,
|
|
103
|
+
时间: `${new Date().toLocaleString()}`
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
];
|
|
107
|
+
const requestUUID = error.config._requestUUID;
|
|
108
|
+
const stacktrace = await requestStacktraceMap.get(requestUUID);
|
|
109
|
+
const logMeta = {};
|
|
110
|
+
if (stacktrace) logMeta.stacktrace = stacktrace;
|
|
111
|
+
logger.log({
|
|
112
|
+
level: 'error',
|
|
113
|
+
args: [
|
|
114
|
+
parts.join(''),
|
|
115
|
+
...args
|
|
116
|
+
],
|
|
117
|
+
meta: logMeta
|
|
118
|
+
});
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
48
121
|
logger.log({
|
|
49
|
-
level:
|
|
122
|
+
level: 'error',
|
|
50
123
|
args: [
|
|
51
|
-
|
|
52
|
-
...args
|
|
124
|
+
'请求失败:无响应对象或配置信息'
|
|
53
125
|
],
|
|
54
|
-
meta: {
|
|
55
|
-
logTraceID
|
|
56
|
-
}
|
|
126
|
+
meta: {}
|
|
57
127
|
});
|
|
58
128
|
}
|
|
59
129
|
const requestStacktraceMap = new Map();
|
|
@@ -73,7 +143,7 @@ function initAxiosConfig(axiosInstance) {
|
|
|
73
143
|
logResponse('success', response);
|
|
74
144
|
return response;
|
|
75
145
|
}, (error)=>{
|
|
76
|
-
logResponse('error', error.response);
|
|
146
|
+
logResponse('error', error.response || error);
|
|
77
147
|
return Promise.reject(error);
|
|
78
148
|
});
|
|
79
149
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const isIpad = ()=>{
|
|
2
|
+
const _isIpad = /iPad|Tab|Tablet/i.test(navigator.userAgent) && navigator.maxTouchPoints && navigator.maxTouchPoints > 1;
|
|
3
|
+
return Boolean(_isIpad);
|
|
4
|
+
};
|
|
5
|
+
const isMobile = ()=>{
|
|
6
|
+
const isPhone = /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent);
|
|
7
|
+
return isPhone || isIpad();
|
|
8
|
+
};
|
|
9
|
+
const isIOS = ()=>{
|
|
10
|
+
if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) return true;
|
|
11
|
+
return false;
|
|
12
|
+
};
|
|
13
|
+
export { isIOS, isIpad, isMobile };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
declare module 'axios' {
|
|
3
|
+
interface AxiosRequestConfig {
|
|
4
|
+
meta?: {
|
|
5
|
+
autoJumpToLogin?: boolean;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** 获取axios实例 */
|
|
10
|
+
export declare function getAxiosForBackend(): AxiosInstance;
|
|
11
|
+
export declare const axiosForBackend: AxiosInstance;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import { initAxiosConfig } from "./axiosConfig.js";
|
|
3
|
+
let axiosInstance;
|
|
4
|
+
function getAxiosForBackend() {
|
|
5
|
+
if (!axiosInstance) {
|
|
6
|
+
axiosInstance = axios.create({
|
|
7
|
+
baseURL: process.env.CLIENT_BASE_PATH || '/'
|
|
8
|
+
});
|
|
9
|
+
axiosInstance.interceptors.response.use(null, (err)=>{
|
|
10
|
+
if (err.config.meta?.autoJumpToLogin !== false) {
|
|
11
|
+
const loginUrl = err.response?.headers?.['x-login-url'];
|
|
12
|
+
if (loginUrl) window.location.href = loginUrl;
|
|
13
|
+
}
|
|
14
|
+
return Promise.reject(err);
|
|
15
|
+
});
|
|
16
|
+
initAxiosConfig(axiosInstance);
|
|
17
|
+
}
|
|
18
|
+
return axiosInstance;
|
|
19
|
+
}
|
|
20
|
+
const axiosForBackend = getAxiosForBackend();
|
|
21
|
+
export { axiosForBackend, getAxiosForBackend };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
export declare function getEnv(): 'BOE' | 'PRE' | 'ONLINE';
|
|
1
2
|
/**
|
|
2
3
|
* @internal
|
|
3
4
|
* 获取预览环境父级域名
|
|
4
5
|
*/
|
|
5
|
-
export declare function getPreviewParentOrigin(): "https://miaoda.feishu.cn" | "https://miaoda.feishu-pre.cn" | "https://miaoda.feishu-boe.cn";
|
|
6
|
+
export declare function getPreviewParentOrigin(): "https://force.feishu-boe.cn" | "https://miaoda.feishu.cn" | "https://miaoda.feishu-pre.cn" | "https://miaoda.feishu-boe.cn";
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
function getEnv() {
|
|
2
|
+
const { origin } = window.location;
|
|
3
|
+
if (origin.includes('feishuapp.cn') || origin.includes('miaoda.feishuapp.net')) return 'ONLINE';
|
|
4
|
+
if (origin.includes('fsapp.kundou.cn') || origin.includes('miaoda-pre.feishuapp.net')) return 'PRE';
|
|
5
|
+
return 'BOE';
|
|
6
|
+
}
|
|
1
7
|
function getPreviewParentOrigin() {
|
|
2
8
|
const { origin } = window.location;
|
|
9
|
+
if (origin.includes('force.byted.org')) return 'https://force.feishu-boe.cn';
|
|
3
10
|
if (origin.includes('feishuapp.cn') || origin.includes('miaoda.feishuapp.net')) return 'https://miaoda.feishu.cn';
|
|
4
11
|
if (origin.includes('fsapp.kundou.cn') || origin.includes('miaoda-pre.feishuapp.net')) return 'https://miaoda.feishu-pre.cn';
|
|
5
12
|
return 'https://miaoda.feishu-boe.cn';
|
|
6
13
|
}
|
|
7
|
-
export { getPreviewParentOrigin };
|
|
14
|
+
export { getEnv, getPreviewParentOrigin };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getDataloom } from "../integrations/dataloom.js";
|
|
2
|
+
const pendingRequests = new Map();
|
|
3
|
+
async function fetchUserProfilesByIds(ids) {
|
|
4
|
+
try {
|
|
5
|
+
const dataloom = await getDataloom();
|
|
6
|
+
if (!dataloom) throw new Error('Dataloom client is unavailable');
|
|
7
|
+
const numericIds = ids.map(Number).filter(Number.isFinite);
|
|
8
|
+
if (0 === numericIds.length) return [];
|
|
9
|
+
const response = await dataloom.service.user.getByIds(numericIds);
|
|
10
|
+
return Array.isArray(response?.data) ? response.data : response?.data?.user_list || [];
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error(`Failed to fetch profiles for user IDs ${ids.join(', ')}:`, error);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function fetchWithDeduplication(ids) {
|
|
17
|
+
const key = ids.sort().join(',');
|
|
18
|
+
if (pendingRequests.has(key)) return pendingRequests.get(key);
|
|
19
|
+
const fetchPromise = fetchUserProfilesByIds(ids);
|
|
20
|
+
pendingRequests.set(key, fetchPromise);
|
|
21
|
+
fetchPromise.finally(()=>{
|
|
22
|
+
pendingRequests.delete(key);
|
|
23
|
+
});
|
|
24
|
+
return fetchPromise;
|
|
25
|
+
}
|
|
26
|
+
export { fetchWithDeduplication };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IUserProfile } from '../apis/udt-types';
|
|
2
|
+
export interface ICachedUserProfile {
|
|
3
|
+
profile: IUserProfile;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const cache: Map<string, ICachedUserProfile>;
|
|
7
|
+
export declare const cacheExpiry: number;
|
|
8
|
+
export declare function setCachedUserProfiles(profiles: IUserProfile[]): void;
|
|
9
|
+
export declare function getCachedUserProfiles(ids: string[]): {
|
|
10
|
+
cachedProfiles: IUserProfile[];
|
|
11
|
+
remainingIds: string[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const cache = new Map();
|
|
2
|
+
const cacheExpiry = 1 / 0;
|
|
3
|
+
function setCachedUserProfiles(profiles) {
|
|
4
|
+
const now = Date.now();
|
|
5
|
+
profiles.forEach((profile)=>{
|
|
6
|
+
if (profile && profile.user_id) cache.set(String(profile.user_id), {
|
|
7
|
+
profile,
|
|
8
|
+
timestamp: now
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function getCachedUserProfiles(ids) {
|
|
13
|
+
const cachedProfiles = [];
|
|
14
|
+
const remainingIds = [];
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
ids.forEach((id)=>{
|
|
17
|
+
const cachedItem = cache.get(id);
|
|
18
|
+
if (cachedItem && now - cachedItem.timestamp < cacheExpiry) cachedProfiles.push(cachedItem.profile);
|
|
19
|
+
else remainingIds.push(id);
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
cachedProfiles,
|
|
23
|
+
remainingIds
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export { cache, cacheExpiry, getCachedUserProfiles, setCachedUserProfiles };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lark-apaas/client-toolkit",
|
|
3
|
-
"version": "1.1.21-alpha.auth.dev.
|
|
3
|
+
"version": "1.1.21-alpha.auth.dev.10",
|
|
4
4
|
"types": "./lib/index.d.ts",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
"require": "./lib/index.js",
|
|
16
16
|
"types": "./lib/index.d.ts"
|
|
17
17
|
},
|
|
18
|
+
"./antd-table": {
|
|
19
|
+
"import": "./lib/antd-table.js",
|
|
20
|
+
"require": "./lib/antd-table.js",
|
|
21
|
+
"types": "./lib/antd-table.d.ts"
|
|
22
|
+
},
|
|
18
23
|
"./lib/index.css": "./lib/index.css",
|
|
19
24
|
"./dataloom": {
|
|
20
25
|
"import": "./lib/apis/dataloom.js",
|
|
@@ -55,6 +60,11 @@
|
|
|
55
60
|
"import": "./lib/apis/utils/*.js",
|
|
56
61
|
"require": "./lib/apis/utils/*.js",
|
|
57
62
|
"types": "./lib/apis/utils/*.d.ts"
|
|
63
|
+
},
|
|
64
|
+
"./auth": {
|
|
65
|
+
"import": "./lib/auth.js",
|
|
66
|
+
"require": "./lib/auth.js",
|
|
67
|
+
"types": "./lib/auth.d.ts"
|
|
58
68
|
}
|
|
59
69
|
},
|
|
60
70
|
"scripts": {
|
|
@@ -69,22 +79,25 @@
|
|
|
69
79
|
"storybook": "storybook dev",
|
|
70
80
|
"test": "echo 0",
|
|
71
81
|
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
|
|
72
|
-
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix"
|
|
82
|
+
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
|
|
83
|
+
"prepublishOnly": "npm run build && node scripts/replace-workspace-alias.js"
|
|
73
84
|
},
|
|
74
85
|
"dependencies": {
|
|
75
86
|
"@ant-design/colors": "^7.2.1",
|
|
76
87
|
"@ant-design/cssinjs": "^1.24.0",
|
|
77
|
-
"@data-loom/js": "
|
|
78
|
-
"@lark-apaas/auth-sdk": "0.1.0-alpha.
|
|
79
|
-
"@lark-apaas/miaoda-inspector": "^1.0.
|
|
88
|
+
"@data-loom/js": "0.4.4-auth-alpha.11",
|
|
89
|
+
"@lark-apaas/auth-sdk": "0.1.0-alpha.13",
|
|
90
|
+
"@lark-apaas/miaoda-inspector": "^1.0.5",
|
|
80
91
|
"@radix-ui/react-avatar": "^1.1.10",
|
|
81
92
|
"@radix-ui/react-popover": "^1.1.15",
|
|
82
93
|
"@radix-ui/react-slot": "^1.2.3",
|
|
83
94
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
84
95
|
"@zumer/snapdom": "^1.9.14",
|
|
85
96
|
"axios": "^1.12.2",
|
|
97
|
+
"blueimp-md5": "2.10.0",
|
|
86
98
|
"class-variance-authority": "^0.7.1",
|
|
87
99
|
"clsx": "~2.0.1",
|
|
100
|
+
"crypto-js": "3.1.9-1",
|
|
88
101
|
"dayjs": "^1.11.13",
|
|
89
102
|
"echarts": "^6.0.0",
|
|
90
103
|
"lodash": "^4.17.21",
|
|
@@ -117,6 +130,8 @@
|
|
|
117
130
|
"@tailwindcss/postcss": "^4.1.0",
|
|
118
131
|
"@testing-library/jest-dom": "^6.6.4",
|
|
119
132
|
"@testing-library/react": "^16.3.0",
|
|
133
|
+
"@types/blueimp-md5": "^2.18.2",
|
|
134
|
+
"@types/crypto-js": "^4.2.2",
|
|
120
135
|
"@types/lodash": "^4.17.20",
|
|
121
136
|
"@types/node": "^22.10.2",
|
|
122
137
|
"@types/react": "^18.3.23",
|
|
@@ -142,6 +157,7 @@
|
|
|
142
157
|
"antd": ">=5.26.6",
|
|
143
158
|
"react": ">=16.14.0",
|
|
144
159
|
"react-dom": ">=16.14.0",
|
|
145
|
-
"react-router-dom": ">=6.26.2"
|
|
160
|
+
"react-router-dom": ">=6.26.2",
|
|
161
|
+
"styled-jsx": ">=5.0.0"
|
|
146
162
|
}
|
|
147
163
|
}
|