@pnt-team/pnt-component-frontend 0.0.98 → 0.0.102
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/cjs/api/cos.d.ts +2 -2
- package/lib/cjs/api/index.d.ts +4 -4
- package/lib/cjs/api/index.js +2 -2
- package/lib/cjs/components/PntCosUploader/index.d.ts +2 -3
- package/lib/cjs/components/PntSecureBox/index.d.ts +51 -3
- package/lib/cjs/components/PntSecureBox/index.js +84 -26
- package/lib/cjs/components/PntSecureBox/index.scss +2 -1
- package/lib/cjs/config.d.ts +32 -2
- package/lib/cjs/global.d.ts +9 -0
- package/lib/cjs/hooks/useHighSecurity.d.ts +24 -3
- package/lib/cjs/hooks/useHighSecurity.js +39 -15
- package/lib/cjs/index.d.ts +2 -2
- package/lib/esm/api/cos.d.ts +2 -2
- package/lib/esm/api/index.d.ts +4 -4
- package/lib/esm/api/index.js +2 -1
- package/lib/esm/components/PntCosUploader/index.d.ts +2 -3
- package/lib/esm/components/PntSecureBox/index.d.ts +51 -3
- package/lib/esm/components/PntSecureBox/index.js +86 -17
- package/lib/esm/components/PntSecureBox/index.scss +2 -1
- package/lib/esm/config.d.ts +32 -2
- package/lib/esm/config.js +11 -0
- package/lib/esm/global.d.ts +9 -0
- package/lib/esm/hooks/useHighSecurity.d.ts +24 -3
- package/lib/esm/hooks/useHighSecurity.js +54 -13
- package/lib/esm/index.d.ts +2 -2
- package/lib/umd/pnt-component-frontend.min.css +1 -1
- package/lib/umd/pnt-component-frontend.min.js +1 -1
- package/package.json +9 -3
package/lib/cjs/api/cos.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PntHttpLike } from "../config";
|
|
2
2
|
/**
|
|
3
3
|
* 归一化后的 COS 临时凭证
|
|
4
4
|
* @description 各后端接口字段命名不统一(snake/camel),组件库内部统一为 camelCase
|
|
@@ -99,5 +99,5 @@ export declare const normalizeSnakeCredential: (raw: SnakeCosCredential) => Norm
|
|
|
99
99
|
* @param params 凭证获取参数
|
|
100
100
|
* @param customNormalize 可选的原始响应自定义归一化
|
|
101
101
|
*/
|
|
102
|
-
export declare const fetchCosCredential: (http:
|
|
102
|
+
export declare const fetchCosCredential: (http: PntHttpLike, params: GetCosCredentialParams, customNormalize?: NormalizeCredential) => Promise<NormalizedCosCredential>;
|
|
103
103
|
export {};
|
package/lib/cjs/api/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { commonEesType } from "../config";
|
|
2
|
-
import type { AxiosInstance } from 'axios';
|
|
1
|
+
import type { commonEesType, PntHttpLike } from "../config";
|
|
3
2
|
import { BusinessGameInfoHighSecurityDecryptBody, BusinessGameInfoHighSecurityDecryptResponse, BusinessSelectListBody, BusinessSelectListResponse } from './types/index';
|
|
4
3
|
/**
|
|
5
4
|
* 业务下拉选择列表
|
|
6
5
|
* @param http 由 PntProvider 注入的 axios 实例
|
|
7
6
|
* @param data 请求参数
|
|
8
7
|
*/
|
|
9
|
-
export declare const businessSelectList: (axios:
|
|
8
|
+
export declare const businessSelectList: (axios: PntHttpLike, data: BusinessSelectListBody) => Promise<commonEesType<BusinessSelectListResponse>>;
|
|
10
9
|
/**
|
|
11
10
|
* 高敏信息解锁
|
|
12
11
|
* @param http 由 PntProvider 注入的 axios 实例
|
|
13
12
|
* @param data 请求参数
|
|
13
|
+
* @param url 自定义接口 URL(可选,覆盖默认值)
|
|
14
14
|
*/
|
|
15
|
-
export declare const businessGameInfoHighSecurityDecrypt: (axios:
|
|
15
|
+
export declare const businessGameInfoHighSecurityDecrypt: (axios: PntHttpLike, data: BusinessGameInfoHighSecurityDecryptBody, url?: string) => Promise<commonEesType<BusinessGameInfoHighSecurityDecryptResponse>>;
|
package/lib/cjs/api/index.js
CHANGED
|
@@ -24,8 +24,8 @@ __export(api_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(api_exports);
|
|
26
26
|
var businessSelectList = (axios, data) => axios.post("/business/select/list?audience=/player-network", data);
|
|
27
|
-
var businessGameInfoHighSecurityDecrypt = (axios, data) => axios.post(
|
|
28
|
-
"/v3/business/game_info/high-security-decrypt?audience=/laas-pnt",
|
|
27
|
+
var businessGameInfoHighSecurityDecrypt = (axios, data, url) => axios.post(
|
|
28
|
+
url || "/v3/business/game_info/high-security-decrypt?audience=/laas-pnt",
|
|
29
29
|
data
|
|
30
30
|
);
|
|
31
31
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type CosScene, type GetCosCredentialParams, type NormalizeCredential, type NormalizedCosCredential } from "../../api/cos";
|
|
2
|
-
import { usePntConfig } from "../../config";
|
|
3
|
-
import type { AxiosInstance } from 'axios';
|
|
2
|
+
import { usePntConfig, type PntHttpLike } from "../../config";
|
|
4
3
|
/**
|
|
5
4
|
* 文件名生成策略
|
|
6
5
|
* @description 内置三种策略;如需自定义可传函数
|
|
@@ -117,7 +116,7 @@ export { normalizeSnakeCredential } from "../../api/cos";
|
|
|
117
116
|
* const { fileUrl } = await uploader.upload(file);
|
|
118
117
|
* ```
|
|
119
118
|
*/
|
|
120
|
-
export declare const createPntCosUploader: (http:
|
|
119
|
+
export declare const createPntCosUploader: (http: PntHttpLike, options: PntCosUploadOptions | (() => PntCosUploadOptions)) => PntCosUploader;
|
|
121
120
|
/**
|
|
122
121
|
* COS 直传 Service Hook
|
|
123
122
|
* @description 内置凭证获取 + COS SDK 初始化 + 文件名策略 + URL 拼接,
|
|
@@ -13,9 +13,9 @@ interface PntSecureBoxProps {
|
|
|
13
13
|
dataValue: string;
|
|
14
14
|
/**
|
|
15
15
|
* 环境标识
|
|
16
|
-
* @description 用于区分不同环境(如:dev, test, production
|
|
16
|
+
* @description 用于区分不同环境(如:dev, test, production);可缺省,默认 0
|
|
17
17
|
*/
|
|
18
|
-
env
|
|
18
|
+
env?: string | number;
|
|
19
19
|
/**
|
|
20
20
|
* 游戏 ID
|
|
21
21
|
* @description 标识具体的游戏项目
|
|
@@ -38,10 +38,52 @@ interface PntSecureBoxProps {
|
|
|
38
38
|
* @description 用于记录操作日志和权限验证
|
|
39
39
|
*/
|
|
40
40
|
pageId?: string;
|
|
41
|
+
/**
|
|
42
|
+
* 明文是否也掩码显示
|
|
43
|
+
* @description
|
|
44
|
+
* - false(默认):非加密值直接展示原值
|
|
45
|
+
* - true:非加密值也展示 ******,点击后本地揭示(不调接口,防窥屏)
|
|
46
|
+
*/
|
|
47
|
+
maskPlain?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* 接口变体
|
|
50
|
+
* @description
|
|
51
|
+
* - 'business'(默认):业务级,走 /v3/business/game_info/high-security-decrypt
|
|
52
|
+
* - 'platform':平台级(发布记录页等场景),走 /v3/business/game_info/plat-high-security-decrypt
|
|
53
|
+
*/
|
|
54
|
+
scope?: 'business' | 'platform';
|
|
55
|
+
/**
|
|
56
|
+
* 解锁后是否显示复制按钮
|
|
57
|
+
* @description 默认 true,解锁后按钮文案切换为「复制」;传 false 则解锁后按钮消失(旧行为)
|
|
58
|
+
*/
|
|
59
|
+
copyable?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 复制按钮文案
|
|
62
|
+
* @description 用于适配多语言场景,默认为 'Copy'
|
|
63
|
+
*/
|
|
64
|
+
copyText?: string;
|
|
65
|
+
/**
|
|
66
|
+
* 复制成功后的内联提示文案
|
|
67
|
+
* @description 仅在使用默认复制(未传 onCopy)时生效;
|
|
68
|
+
* 传入非空字符串后,复制成功按钮文案临时切换为该文案 2 秒;默认 'Copied',传 '' 关闭内联提示
|
|
69
|
+
*/
|
|
70
|
+
copySuccessText?: string;
|
|
71
|
+
/**
|
|
72
|
+
* 自定义复制行为
|
|
73
|
+
* @description 传入后替换默认的 navigator.clipboard.writeText;
|
|
74
|
+
* 消费方自行处理复制与反馈(此时 copySuccessText 不再生效)
|
|
75
|
+
*/
|
|
76
|
+
onCopy?: (value: string) => void | Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* 缓存别名
|
|
79
|
+
* @description 当后端 key 相同但密文不同时(如两组 SDK 密钥),用 cacheKey 区分缓存;
|
|
80
|
+
* 请求体仍用 dataKey 作为 key,缓存读写用 cacheKey。默认 cacheKey=dataKey
|
|
81
|
+
*/
|
|
82
|
+
cacheKey?: string;
|
|
41
83
|
}
|
|
42
84
|
/**
|
|
43
85
|
* 高敏信息展示统一组件
|
|
44
|
-
* @description
|
|
86
|
+
* @description 用于统一处理和展示高敏信息,支持脱敏显示、按需获取真实数据、解锁后复制。
|
|
45
87
|
* 通过 PntProvider 注入 http 实例,对接 `/api/v3/business/game_info/high-security-decrypt`。
|
|
46
88
|
*
|
|
47
89
|
* @param {PntSecureBoxProps} props - 组件属性
|
|
@@ -52,6 +94,10 @@ interface PntSecureBoxProps {
|
|
|
52
94
|
* @param {(content: string) => React.ReactNode} props.renderDom - 自定义渲染函数
|
|
53
95
|
* @param {string} [props.viewText] - 自定义查看按钮文案
|
|
54
96
|
* @param {string} [props.pageId] - 页面 ID
|
|
97
|
+
* @param {boolean} [props.copyable=true] - 解锁后是否显示复制按钮
|
|
98
|
+
* @param {string} [props.copyText] - 复制按钮文案
|
|
99
|
+
* @param {string} [props.copySuccessText] - 复制成功内联提示文案
|
|
100
|
+
* @param {(value: string) => void | Promise<void>} [props.onCopy] - 自定义复制行为
|
|
55
101
|
*
|
|
56
102
|
* @example
|
|
57
103
|
* ```tsx
|
|
@@ -64,6 +110,8 @@ interface PntSecureBoxProps {
|
|
|
64
110
|
* gameId={12345}
|
|
65
111
|
* renderDom={(content) => <span>{content}</span>}
|
|
66
112
|
* viewText="查看"
|
|
113
|
+
* copyText="复制"
|
|
114
|
+
* copySuccessText="已复制"
|
|
67
115
|
* />
|
|
68
116
|
* ```
|
|
69
117
|
*
|
|
@@ -24,40 +24,98 @@ __export(PntSecureBox_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(PntSecureBox_exports);
|
|
25
25
|
var import_useHighSecurity = require("../../hooks/useHighSecurity");
|
|
26
26
|
var import_utils = require("../../utils");
|
|
27
|
+
var import_react = require("react");
|
|
27
28
|
var import_index = require("./index.scss");
|
|
28
29
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
30
|
var PntSecureBox = (prop) => {
|
|
30
|
-
const {
|
|
31
|
+
const {
|
|
32
|
+
dataKey,
|
|
33
|
+
dataValue,
|
|
34
|
+
env,
|
|
35
|
+
gameId,
|
|
36
|
+
renderDom,
|
|
37
|
+
viewText,
|
|
38
|
+
pageId,
|
|
39
|
+
maskPlain,
|
|
40
|
+
scope,
|
|
41
|
+
copyable = true,
|
|
42
|
+
copyText,
|
|
43
|
+
copySuccessText = "Copied",
|
|
44
|
+
onCopy,
|
|
45
|
+
cacheKey
|
|
46
|
+
} = prop;
|
|
47
|
+
const storeKey = cacheKey || dataKey;
|
|
31
48
|
const { securityData, isUnlocked, requestSecurityData } = (0, import_useHighSecurity.useHighSecurity)({
|
|
32
49
|
gameId,
|
|
33
|
-
env
|
|
50
|
+
env,
|
|
51
|
+
scope
|
|
34
52
|
});
|
|
53
|
+
const [plainViewed, setPlainViewed] = (0, import_react.useState)(false);
|
|
54
|
+
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
55
|
+
const copyTimer = (0, import_react.useRef)(null);
|
|
56
|
+
(0, import_react.useEffect)(() => {
|
|
57
|
+
return () => {
|
|
58
|
+
if (copyTimer.current)
|
|
59
|
+
clearTimeout(copyTimer.current);
|
|
60
|
+
};
|
|
61
|
+
}, []);
|
|
35
62
|
const isSecurity = (0, import_utils.isSecurityData)(dataValue);
|
|
36
|
-
const unlocked = isSecurity
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
const unlocked = isSecurity ? isUnlocked(storeKey) : maskPlain ? plainViewed : true;
|
|
64
|
+
const displayValue = unlocked ? isSecurity ? securityData[storeKey] || "******" : dataValue : "******";
|
|
65
|
+
const handleView = () => {
|
|
66
|
+
if (isSecurity) {
|
|
67
|
+
requestSecurityData({
|
|
68
|
+
env,
|
|
69
|
+
gameId,
|
|
70
|
+
pageId,
|
|
71
|
+
param: [
|
|
72
|
+
{
|
|
73
|
+
key: dataKey,
|
|
74
|
+
value: dataValue,
|
|
75
|
+
cacheKey: storeKey
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
});
|
|
79
|
+
} else if (maskPlain) {
|
|
80
|
+
setPlainViewed(true);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const handleCopy = (0, import_react.useCallback)(async () => {
|
|
84
|
+
const value = unlocked ? isSecurity ? securityData[storeKey] || "" : dataValue : "";
|
|
85
|
+
if (onCopy) {
|
|
86
|
+
await onCopy(value);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
await navigator.clipboard.writeText(value);
|
|
91
|
+
if (copySuccessText) {
|
|
92
|
+
if (copyTimer.current)
|
|
93
|
+
clearTimeout(copyTimer.current);
|
|
94
|
+
setCopied(true);
|
|
95
|
+
copyTimer.current = setTimeout(
|
|
96
|
+
() => setCopied(false),
|
|
97
|
+
2e3
|
|
98
|
+
);
|
|
59
99
|
}
|
|
60
|
-
)
|
|
100
|
+
} catch (err) {
|
|
101
|
+
console.warn("[pnt-component-frontend] 复制失败", err);
|
|
102
|
+
}
|
|
103
|
+
}, [
|
|
104
|
+
unlocked,
|
|
105
|
+
isSecurity,
|
|
106
|
+
securityData,
|
|
107
|
+
storeKey,
|
|
108
|
+
dataValue,
|
|
109
|
+
onCopy,
|
|
110
|
+
copySuccessText
|
|
111
|
+
]);
|
|
112
|
+
const isSensitive = isSecurity || !!maskPlain;
|
|
113
|
+
const showViewBtn = !unlocked;
|
|
114
|
+
const showCopyBtn = unlocked && isSensitive && copyable;
|
|
115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "pnt-secure-box", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
116
|
+
renderDom(displayValue),
|
|
117
|
+
showViewBtn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "view-icon", onClick: handleView, children: viewText || "View" }),
|
|
118
|
+
showCopyBtn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "copy-icon", onClick: handleCopy, children: copied && copySuccessText ? copySuccessText : copyText || "Copy" })
|
|
61
119
|
] }) });
|
|
62
120
|
};
|
|
63
121
|
var PntSecureBox_default = PntSecureBox;
|
package/lib/cjs/config.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type { AxiosInstance } from 'axios';
|
|
3
2
|
/**
|
|
4
3
|
* 统一响应结构(与后端 commonEesType 对齐)
|
|
5
4
|
*/
|
|
@@ -9,12 +8,43 @@ export interface commonEesType<T> {
|
|
|
9
8
|
data: T;
|
|
10
9
|
ret?: number;
|
|
11
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* 库所需的最小 HTTP 能力(仅 post)。
|
|
13
|
+
* 用结构化类型而非直接依赖 AxiosInstance,
|
|
14
|
+
* 避免与消费方 axios 版本的类型定义强耦合(如 1.13 vs 1.20 的 query 方法差异)。
|
|
15
|
+
* 任何具备 axios 兼容 post 签名的实例均可注入。
|
|
16
|
+
*/
|
|
17
|
+
export interface PntHttpLike {
|
|
18
|
+
get<T = unknown, R = unknown>(url: string, config?: any): Promise<R>;
|
|
19
|
+
post<T = unknown, R = unknown, D = unknown>(url: string, data?: D, config?: any): Promise<R>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 高敏信息解锁接口配置(可选,全局覆盖)
|
|
23
|
+
*/
|
|
24
|
+
export interface PntHighSecurityConfig {
|
|
25
|
+
/**
|
|
26
|
+
* 业务级解密接口 URL,覆盖默认 /api/v3/business/game_info/high-security-decrypt?audience=/laas-pnt
|
|
27
|
+
* @description scope='business'(默认)时使用
|
|
28
|
+
*/
|
|
29
|
+
decryptUrl?: string;
|
|
30
|
+
/**
|
|
31
|
+
* 平台级解密接口 URL,覆盖默认 /api/v3/business/game_info/plat-high-security-decrypt?audience=/laas-pnt
|
|
32
|
+
* @description scope='platform' 时使用(发布记录页等平台级权限校验场景)
|
|
33
|
+
*/
|
|
34
|
+
decryptPlatUrl?: string;
|
|
35
|
+
/** 成功码字段:'code'(默认)或 'ret'(account-business 现状) */
|
|
36
|
+
successCodeField?: 'code' | 'ret';
|
|
37
|
+
/** audience 覆盖(默认 /laas-pnt) */
|
|
38
|
+
audience?: string;
|
|
39
|
+
}
|
|
12
40
|
/**
|
|
13
41
|
* 组件库运行时配置:由消费方通过 PntProvider 注入
|
|
14
42
|
*/
|
|
15
43
|
export interface PntConfig {
|
|
16
44
|
/** 消费方已配置好的 axios 实例(含拦截器、鉴权、baseURL 等) */
|
|
17
|
-
http:
|
|
45
|
+
http: PntHttpLike;
|
|
46
|
+
/** 高敏信息解锁接口全局配置(可选) */
|
|
47
|
+
highSecurity?: PntHighSecurityConfig;
|
|
18
48
|
}
|
|
19
49
|
/**
|
|
20
50
|
* 配置 Provider:消费方在应用根入口包裹一次即可
|
package/lib/cjs/global.d.ts
CHANGED
|
@@ -28,3 +28,12 @@ declare module '*.json' {
|
|
|
28
28
|
const value: any;
|
|
29
29
|
export default value;
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
// use-sync-external-store shim(兼容 React 17,包本身未提供 .d.ts)
|
|
33
|
+
declare module 'use-sync-external-store' {
|
|
34
|
+
export function useSyncExternalStore<A>(
|
|
35
|
+
subscribe: (callback: () => void) => () => void,
|
|
36
|
+
getSnapshot: () => A,
|
|
37
|
+
getServerSnapshot?: () => A,
|
|
38
|
+
): A;
|
|
39
|
+
}
|
|
@@ -1,27 +1,48 @@
|
|
|
1
|
+
import type { PntHighSecurityConfig } from "../config";
|
|
1
2
|
/** 单个解锁项 */
|
|
2
3
|
export interface HighSecurityParamItem {
|
|
3
4
|
/** 字段标识(与后端约定) */
|
|
4
5
|
key: string;
|
|
5
6
|
/** 参数密文(_high_security_: 前缀) */
|
|
6
7
|
value: string;
|
|
8
|
+
/**
|
|
9
|
+
* 缓存别名(可选)
|
|
10
|
+
* @description 当后端 key 相同但密文不同时(如两组 SDK 密钥),
|
|
11
|
+
* 用 cacheKey 区分缓存,请求体仍用 key。默认 cacheKey=key
|
|
12
|
+
*/
|
|
13
|
+
cacheKey?: string;
|
|
7
14
|
}
|
|
15
|
+
/** 单次请求的接口配置覆盖(优先级 > PntProvider 全局配置) */
|
|
16
|
+
export type HighSecurityApiConfig = PntHighSecurityConfig;
|
|
17
|
+
/**
|
|
18
|
+
* 高敏接口变体
|
|
19
|
+
* - 'business'(默认):业务级,走 /api/v3/business/game_info/high-security-decrypt
|
|
20
|
+
* - 'platform':平台级(发布记录页场景),走 /api/v3/business/game_info/plat-high-security-decrypt
|
|
21
|
+
*/
|
|
22
|
+
export type HighSecurityScope = 'business' | 'platform';
|
|
8
23
|
/** 高敏数据解锁请求参数(组件层友好命名,库内部转换为后端 snake_case) */
|
|
9
24
|
export interface HighSecurityRequestParams {
|
|
10
25
|
/** 业务 ID */
|
|
11
26
|
gameId: string | number;
|
|
12
|
-
/**
|
|
13
|
-
env
|
|
27
|
+
/** 环境标识(可缺省,默认 0;以各业务现有约定为准) */
|
|
28
|
+
env?: string | number;
|
|
14
29
|
/** 页面 ID(不传则默认取 location.pathname),用于操作日志和权限校验 */
|
|
15
30
|
pageId?: string;
|
|
16
31
|
/** 需要解锁的参数列表,支持批量 */
|
|
17
32
|
param: HighSecurityParamItem[];
|
|
33
|
+
/** 本次请求的接口配置覆盖(可选) */
|
|
34
|
+
apiConfig?: HighSecurityApiConfig;
|
|
35
|
+
/** 本次请求的接口变体,覆盖 hook 初始化时的 scope */
|
|
36
|
+
scope?: HighSecurityScope;
|
|
18
37
|
}
|
|
19
38
|
/** hook 初始化 scope:传入后 securityData/isUnlocked 自动按该业务+环境过滤 */
|
|
20
39
|
export interface UseHighSecurityOptions {
|
|
21
40
|
/** 当前业务 ID */
|
|
22
41
|
gameId?: string | number;
|
|
23
|
-
/**
|
|
42
|
+
/** 当前环境(可缺省,默认 0) */
|
|
24
43
|
env?: string | number;
|
|
44
|
+
/** 接口变体(默认 'business');发布记录页等平台级场景传 'platform' */
|
|
45
|
+
scope?: HighSecurityScope;
|
|
25
46
|
}
|
|
26
47
|
/** 清缓存过滤条件 */
|
|
27
48
|
export interface ClearSecurityDataFilter {
|
|
@@ -25,6 +25,7 @@ module.exports = __toCommonJS(useHighSecurity_exports);
|
|
|
25
25
|
var import_api = require("../api");
|
|
26
26
|
var import_config = require("../config");
|
|
27
27
|
var import_react = require("react");
|
|
28
|
+
var import_use_sync_external_store = require("use-sync-external-store");
|
|
28
29
|
var buildCacheKey = (gameId, env, key) => `${gameId}:${env}:${key}`;
|
|
29
30
|
var securityCache = /* @__PURE__ */ new Map();
|
|
30
31
|
var inflightRequests = /* @__PURE__ */ new Map();
|
|
@@ -77,11 +78,12 @@ var clearEntries = (filter) => {
|
|
|
77
78
|
};
|
|
78
79
|
var getDefaultPageId = () => typeof window !== "undefined" && window.location ? window.location.pathname : "";
|
|
79
80
|
var useHighSecurity = (options) => {
|
|
80
|
-
const { http } = (0, import_config.usePntConfig)();
|
|
81
|
-
const snapshot = (0,
|
|
81
|
+
const { http, highSecurity: globalHighSecurity } = (0, import_config.usePntConfig)();
|
|
82
|
+
const snapshot = (0, import_use_sync_external_store.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
82
83
|
const scopeGameId = (options == null ? void 0 : options.gameId) === void 0 ? void 0 : String(options.gameId);
|
|
83
84
|
const scopeEnv = (options == null ? void 0 : options.env) === void 0 ? void 0 : String(options.env);
|
|
84
85
|
const hasScope = scopeGameId !== void 0 && scopeEnv !== void 0;
|
|
86
|
+
const optionsScope = options == null ? void 0 : options.scope;
|
|
85
87
|
const securityData = (0, import_react.useMemo)(() => {
|
|
86
88
|
if (!hasScope)
|
|
87
89
|
return {};
|
|
@@ -107,19 +109,28 @@ var useHighSecurity = (options) => {
|
|
|
107
109
|
gameId,
|
|
108
110
|
env,
|
|
109
111
|
pageId,
|
|
110
|
-
param
|
|
112
|
+
param,
|
|
113
|
+
apiConfig,
|
|
114
|
+
scope: paramScope
|
|
111
115
|
}) => {
|
|
116
|
+
var _a;
|
|
112
117
|
const gid = String(gameId);
|
|
113
|
-
const eid = String(env);
|
|
118
|
+
const eid = String(env != null ? env : 0);
|
|
119
|
+
const merged = {
|
|
120
|
+
...globalHighSecurity,
|
|
121
|
+
...apiConfig
|
|
122
|
+
};
|
|
123
|
+
const successCodeField = merged.successCodeField || "code";
|
|
114
124
|
const result = new Array(
|
|
115
125
|
param.length
|
|
116
126
|
);
|
|
117
127
|
const missing = [];
|
|
118
128
|
const missingIndexes = [];
|
|
119
129
|
param.forEach((item, index) => {
|
|
120
|
-
const
|
|
130
|
+
const storeKey = item.cacheKey || item.key;
|
|
131
|
+
const cached = snapshot.get(buildCacheKey(gid, eid, storeKey));
|
|
121
132
|
if (cached !== void 0) {
|
|
122
|
-
result[index] = { key: item.key, value: cached };
|
|
133
|
+
result[index] = { key: item.key, value: cached, cacheKey: storeKey };
|
|
123
134
|
} else {
|
|
124
135
|
missing.push({ key: item.key, value: item.value });
|
|
125
136
|
missingIndexes.push(index);
|
|
@@ -132,30 +143,43 @@ var useHighSecurity = (options) => {
|
|
|
132
143
|
}
|
|
133
144
|
const body = {
|
|
134
145
|
game_id: Number(gameId),
|
|
135
|
-
env: Number(env),
|
|
146
|
+
env: Number(env != null ? env : 0),
|
|
136
147
|
page_id: pageId || getDefaultPageId(),
|
|
137
148
|
param: missing
|
|
138
149
|
};
|
|
150
|
+
const scope = (_a = paramScope != null ? paramScope : optionsScope) != null ? _a : "business";
|
|
151
|
+
const audience = merged.audience || "/laas-pnt";
|
|
152
|
+
const url = scope === "platform" ? merged.decryptPlatUrl || `/api/v3/business/game_info/plat-high-security-decrypt?audience=${audience}` : merged.decryptUrl || `/api/v3/business/game_info/high-security-decrypt?audience=${audience}`;
|
|
139
153
|
const requestKey = `${gid}:${eid}:${missing.map((item) => `${item.key}${item.value}`).join("")}`;
|
|
140
154
|
const existing = inflightRequests.get(requestKey);
|
|
141
155
|
if (existing)
|
|
142
156
|
return existing;
|
|
143
157
|
const promise = (async () => {
|
|
144
|
-
var
|
|
158
|
+
var _a2, _b;
|
|
145
159
|
try {
|
|
146
|
-
const res = await (0, import_api.businessGameInfoHighSecurityDecrypt)(http, body);
|
|
147
|
-
|
|
160
|
+
const res = await (0, import_api.businessGameInfoHighSecurityDecrypt)(http, body, url);
|
|
161
|
+
const successCode = Number(
|
|
162
|
+
(_a2 = res[successCodeField]) != null ? _a2 : res.code
|
|
163
|
+
);
|
|
164
|
+
if (successCode === 0 && Array.isArray(res.data)) {
|
|
148
165
|
const decrypted = res.data.map((raw) => {
|
|
149
|
-
var
|
|
166
|
+
var _a3;
|
|
150
167
|
if (raw && typeof raw === "object" && "key" in raw) {
|
|
151
168
|
const item = raw;
|
|
152
169
|
if (typeof item.key === "string") {
|
|
153
|
-
return { key: item.key, value: String((
|
|
170
|
+
return { key: item.key, value: String((_a3 = item.value) != null ? _a3 : "") };
|
|
154
171
|
}
|
|
155
172
|
}
|
|
156
173
|
return null;
|
|
157
174
|
}).filter((item) => item !== null);
|
|
158
|
-
|
|
175
|
+
const toStore = decrypted.map((d) => {
|
|
176
|
+
const matchIdx = missingIndexes.find(
|
|
177
|
+
(i) => param[i].key === d.key
|
|
178
|
+
);
|
|
179
|
+
const storeKey = matchIdx !== void 0 ? param[matchIdx].cacheKey || d.key : d.key;
|
|
180
|
+
return { key: d.key, value: d.value, cacheKey: storeKey };
|
|
181
|
+
});
|
|
182
|
+
setEntries(gid, eid, toStore);
|
|
159
183
|
decrypted.forEach((item) => {
|
|
160
184
|
const index = missingIndexes.find(
|
|
161
185
|
(i) => param[i].key === item.key
|
|
@@ -166,7 +190,7 @@ var useHighSecurity = (options) => {
|
|
|
166
190
|
} else {
|
|
167
191
|
console.warn(
|
|
168
192
|
"[pnt-component-frontend] high-security-decrypt 解锁失败",
|
|
169
|
-
(
|
|
193
|
+
(_b = res == null ? void 0 : res.msg) != null ? _b : res[successCodeField]
|
|
170
194
|
);
|
|
171
195
|
}
|
|
172
196
|
} catch (error) {
|
|
@@ -184,7 +208,7 @@ var useHighSecurity = (options) => {
|
|
|
184
208
|
inflightRequests.set(requestKey, promise);
|
|
185
209
|
return promise;
|
|
186
210
|
},
|
|
187
|
-
[http, snapshot]
|
|
211
|
+
[http, snapshot, globalHighSecurity, optionsScope]
|
|
188
212
|
);
|
|
189
213
|
const clearSecurityData = (0, import_react.useCallback)((filter) => {
|
|
190
214
|
clearEntries(filter);
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { PntProvider, usePntConfig, type PntConfig, type commonEesType, } from './config';
|
|
1
|
+
export { PntProvider, usePntConfig, type PntConfig, type PntHttpLike, type PntHighSecurityConfig, type commonEesType, } from './config';
|
|
2
2
|
export { default as PntImage } from './components/PntImage';
|
|
3
3
|
export { default as PntBusinessSelect } from './components/PntBusinessSelect';
|
|
4
4
|
export { default as PntSecureBox } from './components/PntSecureBox';
|
|
@@ -6,6 +6,6 @@ export { default as PntUpload } from './components/PntUpload';
|
|
|
6
6
|
export type { PntUploadErrorPhase, PntUploadProps, PntUploadTexts, } from './components/PntUpload';
|
|
7
7
|
export { createPntCosUploader, normalizeSnakeCredential, default as usePntCosUploader, type CosScene, type FileNameStrategy, type GetCosCredentialParams, type NormalizeCredential, type NormalizedCosCredential, type PntCosRequestOverrides, type PntCosUploadOptions, type PntCosUploadResult, type PntCosUploader as PntCosUploaderInstance, } from './components/PntCosUploader';
|
|
8
8
|
export { useHighSecurity } from './hooks/useHighSecurity';
|
|
9
|
-
export type { ClearSecurityDataFilter, HighSecurityParamItem, HighSecurityRequestParams, UseHighSecurityOptions, UseHighSecurityResult, } from './hooks/useHighSecurity';
|
|
9
|
+
export type { ClearSecurityDataFilter, HighSecurityApiConfig, HighSecurityParamItem, HighSecurityRequestParams, HighSecurityScope, UseHighSecurityOptions, UseHighSecurityResult, } from './hooks/useHighSecurity';
|
|
10
10
|
export { isSecurityData } from './utils';
|
|
11
11
|
export { default as PntGeneralLayout } from './components/PntGeneralLayout';
|
package/lib/esm/api/cos.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PntHttpLike } from "../config";
|
|
2
2
|
/**
|
|
3
3
|
* 归一化后的 COS 临时凭证
|
|
4
4
|
* @description 各后端接口字段命名不统一(snake/camel),组件库内部统一为 camelCase
|
|
@@ -99,5 +99,5 @@ export declare const normalizeSnakeCredential: (raw: SnakeCosCredential) => Norm
|
|
|
99
99
|
* @param params 凭证获取参数
|
|
100
100
|
* @param customNormalize 可选的原始响应自定义归一化
|
|
101
101
|
*/
|
|
102
|
-
export declare const fetchCosCredential: (http:
|
|
102
|
+
export declare const fetchCosCredential: (http: PntHttpLike, params: GetCosCredentialParams, customNormalize?: NormalizeCredential) => Promise<NormalizedCosCredential>;
|
|
103
103
|
export {};
|
package/lib/esm/api/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { commonEesType } from "../config";
|
|
2
|
-
import type { AxiosInstance } from 'axios';
|
|
1
|
+
import type { commonEesType, PntHttpLike } from "../config";
|
|
3
2
|
import { BusinessGameInfoHighSecurityDecryptBody, BusinessGameInfoHighSecurityDecryptResponse, BusinessSelectListBody, BusinessSelectListResponse } from './types/index';
|
|
4
3
|
/**
|
|
5
4
|
* 业务下拉选择列表
|
|
6
5
|
* @param http 由 PntProvider 注入的 axios 实例
|
|
7
6
|
* @param data 请求参数
|
|
8
7
|
*/
|
|
9
|
-
export declare const businessSelectList: (axios:
|
|
8
|
+
export declare const businessSelectList: (axios: PntHttpLike, data: BusinessSelectListBody) => Promise<commonEesType<BusinessSelectListResponse>>;
|
|
10
9
|
/**
|
|
11
10
|
* 高敏信息解锁
|
|
12
11
|
* @param http 由 PntProvider 注入的 axios 实例
|
|
13
12
|
* @param data 请求参数
|
|
13
|
+
* @param url 自定义接口 URL(可选,覆盖默认值)
|
|
14
14
|
*/
|
|
15
|
-
export declare const businessGameInfoHighSecurityDecrypt: (axios:
|
|
15
|
+
export declare const businessGameInfoHighSecurityDecrypt: (axios: PntHttpLike, data: BusinessGameInfoHighSecurityDecryptBody, url?: string) => Promise<commonEesType<BusinessGameInfoHighSecurityDecryptResponse>>;
|
package/lib/esm/api/index.js
CHANGED
|
@@ -9,5 +9,6 @@ export const businessSelectList = (axios, data) => axios.post('/business/select/
|
|
|
9
9
|
* 高敏信息解锁
|
|
10
10
|
* @param http 由 PntProvider 注入的 axios 实例
|
|
11
11
|
* @param data 请求参数
|
|
12
|
+
* @param url 自定义接口 URL(可选,覆盖默认值)
|
|
12
13
|
*/
|
|
13
|
-
export const businessGameInfoHighSecurityDecrypt = (axios, data) => axios.post('/v3/business/game_info/high-security-decrypt?audience=/laas-pnt', data);
|
|
14
|
+
export const businessGameInfoHighSecurityDecrypt = (axios, data, url) => axios.post(url || '/v3/business/game_info/high-security-decrypt?audience=/laas-pnt', data);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type CosScene, type GetCosCredentialParams, type NormalizeCredential, type NormalizedCosCredential } from "../../api/cos";
|
|
2
|
-
import { usePntConfig } from "../../config";
|
|
3
|
-
import type { AxiosInstance } from 'axios';
|
|
2
|
+
import { usePntConfig, type PntHttpLike } from "../../config";
|
|
4
3
|
/**
|
|
5
4
|
* 文件名生成策略
|
|
6
5
|
* @description 内置三种策略;如需自定义可传函数
|
|
@@ -117,7 +116,7 @@ export { normalizeSnakeCredential } from "../../api/cos";
|
|
|
117
116
|
* const { fileUrl } = await uploader.upload(file);
|
|
118
117
|
* ```
|
|
119
118
|
*/
|
|
120
|
-
export declare const createPntCosUploader: (http:
|
|
119
|
+
export declare const createPntCosUploader: (http: PntHttpLike, options: PntCosUploadOptions | (() => PntCosUploadOptions)) => PntCosUploader;
|
|
121
120
|
/**
|
|
122
121
|
* COS 直传 Service Hook
|
|
123
122
|
* @description 内置凭证获取 + COS SDK 初始化 + 文件名策略 + URL 拼接,
|