@morehao/ark-iam-react 0.0.0-stage → 1.0.0

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.

Potentially problematic release.


This version of @morehao/ark-iam-react might be problematic. Click here for more details.

Files changed (66) hide show
  1. package/README.md +83 -2
  2. package/dist/_types/api/index.d.ts +5 -0
  3. package/dist/_types/api/index.js +185 -0
  4. package/dist/_types/api/index.js.map +1 -0
  5. package/dist/_types/api/request.d.ts +34 -0
  6. package/dist/_types/api/resources/auth.d.ts +13 -0
  7. package/dist/_types/api/resources/platform.d.ts +80 -0
  8. package/dist/_types/api/sessionProbe.d.ts +13 -0
  9. package/dist/_types/auth/AuthProvider.d.ts +27 -0
  10. package/dist/_types/auth/config.d.ts +23 -0
  11. package/dist/_types/auth/guards.d.ts +1 -0
  12. package/dist/_types/auth/hooks.d.ts +11 -0
  13. package/dist/_types/auth/index.d.ts +8 -0
  14. package/dist/_types/auth/index.js +190 -0
  15. package/dist/_types/auth/index.js.map +1 -0
  16. package/dist/_types/auth/tenant.d.ts +3 -0
  17. package/dist/_types/types/auth.d.ts +62 -0
  18. package/dist/_types/types/department.d.ts +52 -0
  19. package/dist/_types/types/index.d.ts +5 -0
  20. package/dist/_types/types/index.js +14 -0
  21. package/dist/_types/types/index.js.map +1 -0
  22. package/dist/_types/types/platform.d.ts +347 -0
  23. package/dist/_types/types/response.d.ts +14 -0
  24. package/dist/_types/types/tenant.d.ts +243 -0
  25. package/dist/_types/ui/AppShell.d.ts +16 -0
  26. package/dist/_types/ui/EllipsisCell.d.ts +16 -0
  27. package/dist/_types/ui/IDCell.d.ts +14 -0
  28. package/dist/_types/ui/InitialPasswordModal.d.ts +18 -0
  29. package/dist/_types/ui/LoginPage.d.ts +6 -0
  30. package/dist/_types/ui/MainLayout.d.ts +14 -0
  31. package/dist/_types/ui/NameLink.d.ts +18 -0
  32. package/dist/_types/ui/PageContainer.d.ts +15 -0
  33. package/dist/_types/ui/ProfileCenter.d.ts +6 -0
  34. package/dist/_types/ui/RemoteSelect.d.ts +57 -0
  35. package/dist/_types/ui/RowActions.d.ts +36 -0
  36. package/dist/_types/ui/TenantSwitcher.d.ts +1 -0
  37. package/dist/_types/ui/TimeCell.d.ts +53 -0
  38. package/dist/_types/ui/columns.d.ts +116 -0
  39. package/dist/_types/ui/format.d.ts +20 -0
  40. package/dist/_types/ui/index.d.ts +25 -0
  41. package/dist/_types/ui/index.js +1233 -0
  42. package/dist/_types/ui/index.js.map +1 -0
  43. package/dist/_types/ui/status.d.ts +38 -0
  44. package/dist/_types/ui/theme.d.ts +49 -0
  45. package/dist/api.d.ts +1 -0
  46. package/dist/api.js +50 -0
  47. package/dist/api.js.map +1 -0
  48. package/dist/auth.d.ts +1 -0
  49. package/dist/auth.js +17 -0
  50. package/dist/auth.js.map +1 -0
  51. package/dist/index-BQuRl5A6.js +185 -0
  52. package/dist/index-BQuRl5A6.js.map +1 -0
  53. package/dist/index-D3uUqZ5c.js +190 -0
  54. package/dist/index-D3uUqZ5c.js.map +1 -0
  55. package/dist/index-DnhMUOxg.js +1233 -0
  56. package/dist/index-DnhMUOxg.js.map +1 -0
  57. package/dist/index.d.ts +4 -0
  58. package/dist/index.js +109 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/types.d.ts +1 -0
  61. package/dist/types.js +14 -0
  62. package/dist/types.js.map +1 -0
  63. package/dist/ui.d.ts +1 -0
  64. package/dist/ui.js +46 -0
  65. package/dist/ui.js.map +1 -0
  66. package/package.json +80 -3
package/README.md CHANGED
@@ -1,3 +1,84 @@
1
- # Temporary Holding Version
1
+ # @morehao/ark-iam-react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ GoArk IAM 前端门面包(React + antd 5)。**对外只发布这一个包**,聚合了内部 `@ark-iam/{types,api,auth,ui}` 的能力,代码与类型均已打进自身 `dist`,安装本包即可使用全部能力。
4
+
5
+ 提供四类能力(按 ESM 子路径暴露,可按需引入):
6
+
7
+ | 子路径 | 作用 | 关键导出 |
8
+ |---|---|---|
9
+ | `@morehao/ark-iam-react/types` | 纯类型与错误码枚举(**零重依赖**,不含 antd/react) | `BizCode`、各类 `*Req`/`*Resp` 类型 |
10
+ | `@morehao/ark-iam-react/api` | 业务 API 客户端(axios 实例 + 拦截器) | `createApiClient`、默认 `request`、`setUserProvider`、`setSessionExpiredHandler` |
11
+ | `@morehao/ark-iam-react/auth` | OIDC 登录(PKCE)+ 租户切换 / 登出钩子 | `createAuthProvider`、`fetchRuntimeConfig`、`useTenantSwitching`、`useLogout`、`useAuthGuard` |
12
+ | `@morehao/ark-iam-react/ui` | 设计令牌 + 列表页列工厂 + 骨架组件 | `themeConfig`、`tokens`、`actionColumn`、`tableScrollX`、`AppShell`、`MainLayout` 等 |
13
+ | `@morehao/ark-iam-react` | 上面四层全部 re-export(一把梭) | 全部 |
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ pnpm add @morehao/ark-iam-react
19
+ # 以下为 peer,由宿主提供(只引 @morehao/ark-iam-react/types 时可不必装 antd):
20
+ pnpm add antd@^5.22.0 react@^18.3.1 react-dom@^18.3.1 react-router-dom@^7.15.0
21
+ ```
22
+
23
+ > 追求体积请用子路径(如只 `import { BizCode } from '@morehao/ark-iam-react/types'` 不会拉入 antd);图省事才从根入口 `@morehao/ark-iam-react` 全量引入。
24
+
25
+ ## 主题
26
+
27
+ ```tsx
28
+ import { ConfigProvider } from 'antd'
29
+ import zhCN from 'antd/locale/zh_CN'
30
+ import { themeConfig } from '@morehao/ark-iam-react/ui'
31
+
32
+ <ConfigProvider locale={zhCN} theme={themeConfig}>
33
+ <App />
34
+ </ConfigProvider>
35
+ ```
36
+
37
+ 或直接用 `AppShell`(内部已包好 `ConfigProvider` + `themeConfig` + antd `App` 上下文)。
38
+
39
+ ## 登录
40
+
41
+ ```tsx
42
+ import { createAuthProvider } from '@morehao/ark-iam-react/auth'
43
+
44
+ // 工厂:返回一个 AuthProvider 组件。运行期会先拉 {base}/config.json 覆盖默认值。
45
+ const AuthProvider = createAuthProvider({ clientID: 'my_app_web' })
46
+
47
+ <AuthProvider><App /></AuthProvider>
48
+ ```
49
+
50
+ `createAuthProvider` 参数:`clientID / clientSecret / issuer / redirectPath / postLogoutRedirectPath / getExtraQueryParams / useRuntimeConfig / runtimeConfigBase`。配置优先级:**props > `/config.json` > `VITE_*` > 相对默认值**。
51
+
52
+ ## 请求
53
+
54
+ ```ts
55
+ import { createApiClient } from '@morehao/ark-iam-react/api'
56
+ const api = createApiClient({ baseURL: 'https://iam.example.com/v1', timeout: 15000 })
57
+ ```
58
+
59
+ `createApiClient({ baseURL, timeout, headers })` 返回 axios 实例,内置 401 自动跳登录、业务码、`silent` 抑制提示等拦截逻辑;默认单例 `request` 供同源 `/v1` 场景使用。
60
+
61
+ ## 列表页操作列(最小示例)
62
+
63
+ ```tsx
64
+ import { actionColumn, nameColumn, tableScrollX } from '@morehao/ark-iam-react/ui'
65
+ import { Table } from 'antd'
66
+
67
+ const columns = [
68
+ nameColumn({ dataIndex: 'name', onClick: (r) => openDetail(r) }),
69
+ actionColumn({
70
+ max: 2,
71
+ actions: (r) => [
72
+ { key: 'edit', label: '编辑', onClick: () => handleEdit(r) },
73
+ { key: 'del', label: '删除', danger: true, confirm: '确认删除?', onClick: () => handleDelete(r) },
74
+ ],
75
+ }),
76
+ ]
77
+ <Table tableLayout="fixed" scroll={{ x: tableScrollX(columns) }} columns={columns} dataSource={rows} rowKey="id" />
78
+ ```
79
+
80
+ 完整接入说明见 `docs/design/application-integration-guide.md` §12「前端组件接入」;视觉规范见仓库根 `frontend/DESIGN.md`。
81
+
82
+ ## peerDependencies 口径
83
+
84
+ UI 框架层(`react` / `react-dom` / `antd`(`^5.22`) / `@ant-design/icons`(`^5.4`) / `react-router-dom`(`^7.15`))作为 peer 由宿主统一版本,避免重复安装导致主题/Context 断裂;纯工具依赖(`axios` 等)由本包 dependencies 带入。
@@ -0,0 +1,5 @@
1
+ export { default as request, createApiClient, setUserProvider, setSessionExpiredHandler } from './request';
2
+ export type { CreateApiClientOptions } from './request';
3
+ export { useSSOSessionProbe } from './sessionProbe';
4
+ export * from './resources/auth';
5
+ export * from './resources/platform';
@@ -0,0 +1,185 @@
1
+ import axios from "axios";
2
+ import { message } from "antd";
3
+ import { BizCode } from "@ark-iam/types";
4
+ import { useEffect } from "react";
5
+ let userProvider = null;
6
+ let sessionExpiredHandler = null;
7
+ function setUserProvider(provider) {
8
+ userProvider = provider;
9
+ }
10
+ function setSessionExpiredHandler(handler) {
11
+ sessionExpiredHandler = handler;
12
+ }
13
+ function attachInterceptors(instance) {
14
+ instance.interceptors.request.use((config) => {
15
+ const user = userProvider == null ? void 0 : userProvider();
16
+ if ((user == null ? void 0 : user.access_token) && config.headers) {
17
+ config.headers.Authorization = `Bearer ${user.access_token}`;
18
+ }
19
+ return config;
20
+ });
21
+ instance.interceptors.response.use(
22
+ (response) => {
23
+ var _a;
24
+ const { code, msg } = response.data;
25
+ if (code === BizCode.Success) return response.data.data;
26
+ const isLogoutRequest = (_a = response.config.url) == null ? void 0 : _a.includes("/auth/logout");
27
+ if (code === BizCode.TokenExpired || code === BizCode.TokenInvalid || code === BizCode.Unauthorized) {
28
+ if (isLogoutRequest) return Promise.reject(new Error(msg || "session expired"));
29
+ handleSessionExpired();
30
+ return Promise.reject(new Error(msg || "未认证"));
31
+ }
32
+ if (code === BizCode.Forbidden || code === BizCode.PermissionDenied) {
33
+ if (!response.config.silent) message.warning("暂无权限访问");
34
+ return Promise.reject(new Error(msg || "暂无权限"));
35
+ }
36
+ if (!response.config.silent) message.error(msg || "请求失败");
37
+ return Promise.reject(new Error(msg || "请求失败"));
38
+ },
39
+ async (error) => {
40
+ var _a, _b, _c;
41
+ if (((_a = error.response) == null ? void 0 : _a.status) === 401) {
42
+ handleSessionExpired();
43
+ return Promise.reject(error);
44
+ }
45
+ const data = (_b = error.response) == null ? void 0 : _b.data;
46
+ if (!((_c = error.config) == null ? void 0 : _c.silent)) message.error((data == null ? void 0 : data.msg) || "请求失败");
47
+ return Promise.reject(error);
48
+ }
49
+ );
50
+ return instance;
51
+ }
52
+ function handleSessionExpired() {
53
+ sessionExpiredHandler == null ? void 0 : sessionExpiredHandler();
54
+ window.location.href = "/";
55
+ }
56
+ function createApiClient(opts = {}) {
57
+ const instance = axios.create({
58
+ baseURL: opts.baseURL ?? "/v1",
59
+ timeout: opts.timeout ?? 3e4,
60
+ headers: opts.headers
61
+ });
62
+ return attachInterceptors(instance);
63
+ }
64
+ const request = createApiClient();
65
+ function useSSOSessionProbe(auth) {
66
+ useEffect(() => {
67
+ var _a;
68
+ if (!((_a = auth.events) == null ? void 0 : _a.addSilentRenewError)) return;
69
+ const unsub = auth.events.addSilentRenewError(() => {
70
+ void auth.removeUser();
71
+ });
72
+ return unsub;
73
+ }, [auth.events]);
74
+ }
75
+ const getUserinfo = () => request.get("/auth/userinfo");
76
+ const getMyTenants = () => request.get("/auth/me/tenants");
77
+ const logoutAPI = (refreshToken) => request.post("/auth/logout", { refreshToken });
78
+ const logoutAllAPI = (refreshToken) => request.post("/auth/logoutAll", { refreshToken });
79
+ const getPersonDetail = () => request.get("/auth/me");
80
+ const updatePassword = (req) => request.post("/auth/me/changePassword", req);
81
+ const getSessionList = (params) => request.get("/auth/me/sessions", { params });
82
+ const revokeSession = (sessionID) => request.delete(`/auth/me/sessions/${sessionID}`);
83
+ const revokeAllSessions = () => request.delete("/auth/me/sessions");
84
+ const getApplicationPageList = (data) => request.get("/platform/applications", { params: data });
85
+ const getApplicationDetail = (appID, config) => request.get(`/platform/applications/${appID}`, config);
86
+ const createApplication = (data) => request.post("/platform/applications", data);
87
+ const updateApplication = (data) => {
88
+ const { appID, ...body } = data;
89
+ return request.put(`/platform/applications/${appID}`, body);
90
+ };
91
+ const deleteApplication = (appID) => request.delete(`/platform/applications/${appID}`);
92
+ const getOAuthClientPageList = (data) => request.get("/platform/application-clients", { params: data });
93
+ const getOAuthClientDetail = (applicationClientID) => request.get(`/platform/application-clients/${applicationClientID}`);
94
+ const createOAuthClient = (data) => request.post("/platform/application-clients", data);
95
+ const updateOAuthClient = (data) => {
96
+ const { applicationClientID, ...body } = data;
97
+ return request.put(`/platform/application-clients/${applicationClientID}`, body);
98
+ };
99
+ const deleteOAuthClient = (applicationClientID) => request.delete(`/platform/application-clients/${applicationClientID}`);
100
+ const listOAuthSecrets = (applicationClientID) => request.get(`/platform/application-clients/${applicationClientID}/secrets`);
101
+ const createOAuthSecret = (data) => {
102
+ const { applicationClientID, ...body } = data;
103
+ return request.post(`/platform/application-clients/${applicationClientID}/secrets`, body);
104
+ };
105
+ const deleteOAuthSecret = (applicationClientID, secretID) => request.delete(`/platform/application-clients/${applicationClientID}/secrets/${secretID}`);
106
+ const getTenantPageList = (data) => request.get("/platform/tenants", { params: data });
107
+ const createTenant = (data) => request.post("/platform/tenants", data);
108
+ const resetTenantAdminPassword = (tenantID) => request.post(`/platform/tenants/${tenantID}/builtin-admin/reset-password`);
109
+ const updateTenant = (data) => {
110
+ const { tenantID, ...body } = data;
111
+ return request.put(`/platform/tenants/${tenantID}`, body);
112
+ };
113
+ const deleteTenant = (tenantID) => request.delete(`/platform/tenants/${tenantID}`);
114
+ const getTenantApplicationPageList = (data) => request.get("/platform/tenant-applications", { params: data });
115
+ const createTenantApplication = (data) => request.post("/platform/tenant-applications", data);
116
+ const updateTenantApplication = (data) => {
117
+ const { tenantAppID, ...body } = data;
118
+ return request.put(`/platform/tenant-applications/${tenantAppID}`, body);
119
+ };
120
+ const deleteTenantApplication = (tenantAppID) => request.delete(`/platform/tenant-applications/${tenantAppID}`);
121
+ const getMenuTree = (appID) => request.get("/platform/menus/tree", { params: { appID } });
122
+ const getMyMenuTree = () => request.get("/platform/menus/my");
123
+ const createMenu = (data) => request.post("/platform/menus", data);
124
+ const updateMenu = (data) => {
125
+ const { menuID, ...body } = data;
126
+ return request.put(`/platform/menus/${menuID}`, body);
127
+ };
128
+ const deleteMenu = (menuID) => request.delete(`/platform/menus/${menuID}`);
129
+ const getDomainPageList = (data) => request.get("/platform/domains", { params: data });
130
+ const getDomainDetail = (id) => request.get(`/platform/domains/${id}`);
131
+ const createDomain = (domain) => request.post("/platform/domains", { domain });
132
+ const updateDomain = (data) => {
133
+ const { id, ...body } = data;
134
+ return request.put(`/platform/domains/${id}`, body);
135
+ };
136
+ const deleteDomain = (id) => request.delete(`/platform/domains/${id}`);
137
+ export {
138
+ createApiClient,
139
+ createApplication,
140
+ createDomain,
141
+ createMenu,
142
+ createOAuthClient,
143
+ createOAuthSecret,
144
+ createTenant,
145
+ createTenantApplication,
146
+ deleteApplication,
147
+ deleteDomain,
148
+ deleteMenu,
149
+ deleteOAuthClient,
150
+ deleteOAuthSecret,
151
+ deleteTenant,
152
+ deleteTenantApplication,
153
+ getApplicationDetail,
154
+ getApplicationPageList,
155
+ getDomainDetail,
156
+ getDomainPageList,
157
+ getMenuTree,
158
+ getMyMenuTree,
159
+ getMyTenants,
160
+ getOAuthClientDetail,
161
+ getOAuthClientPageList,
162
+ getPersonDetail,
163
+ getSessionList,
164
+ getTenantApplicationPageList,
165
+ getTenantPageList,
166
+ getUserinfo,
167
+ listOAuthSecrets,
168
+ logoutAPI,
169
+ logoutAllAPI,
170
+ request,
171
+ resetTenantAdminPassword,
172
+ revokeAllSessions,
173
+ revokeSession,
174
+ setSessionExpiredHandler,
175
+ setUserProvider,
176
+ updateApplication,
177
+ updateDomain,
178
+ updateMenu,
179
+ updateOAuthClient,
180
+ updatePassword,
181
+ updateTenant,
182
+ updateTenantApplication,
183
+ useSSOSessionProbe
184
+ };
185
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/request.ts","../src/sessionProbe.ts","../src/resources/auth.ts","../src/resources/platform.ts"],"sourcesContent":["import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig } from 'axios'\nimport { message } from 'antd'\nimport { BizCode } from '@ark-iam/types'\n\n/**\n * silent:本次请求属于 best-effort 探测,失败由调用方自行兜底\n * (典型场景:菜单页首屏恢复\"上次选择的应用\",该应用可能已被删除或换库,旧 ID 失效),\n * 此时不弹全局提示,避免每次进页面都弹一个调用方已经处理掉的错误。\n *\n * 语义边界:silent 只抑制「提示」(message.error / message.warning);\n * 401/令牌失效的会话处置(handleSessionExpired → 跳登录页)是流程控制,不受 silent 影响。\n */\ndeclare module 'axios' {\n export interface AxiosRequestConfig {\n silent?: boolean\n }\n}\n\nlet userProvider: (() => { access_token: string } | null | undefined) | null = null\n\n// sessionExpiredHandler 由 auth 层注册(见 @ark-iam/auth hooks):\n// 当 API 返回 401(SSO 会话已被其它端点全局登出撤销)时,先清除本地 user,\n// 再跳转登录页,避免\"401 → 刷新 → sessionStorage 残留 user → 再 401\"的循环。\nlet sessionExpiredHandler: (() => void) | null = null\n\nexport function setUserProvider(provider: () => { access_token: string } | null | undefined) {\n userProvider = provider\n}\n\nexport function setSessionExpiredHandler(handler: () => void) {\n sessionExpiredHandler = handler\n}\n\nexport interface CreateApiClientOptions {\n /** 业务 API 基址(含版本段),如 '/v1' 或 'https://iam.example.com/v1'。默认 '/v1'。 */\n baseURL?: string\n /** 请求超时(毫秒),默认 30000。 */\n timeout?: number\n /** 追加到每个请求的静态请求头。 */\n headers?: Record<string, string>\n}\n\nfunction attachInterceptors(instance: AxiosInstance) {\n instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {\n const user = userProvider?.()\n if (user?.access_token && config.headers) {\n config.headers.Authorization = `Bearer ${user.access_token}`\n }\n return config\n })\n\n instance.interceptors.response.use(\n (response) => {\n const { code, msg } = response.data as { code: number; msg: string }\n if (code === BizCode.Success) return response.data.data\n\n const isLogoutRequest = response.config.url?.includes('/auth/logout')\n\n if (code === BizCode.TokenExpired || code === BizCode.TokenInvalid || code === BizCode.Unauthorized) {\n if (isLogoutRequest) return Promise.reject(new Error(msg || 'session expired'))\n handleSessionExpired()\n return Promise.reject(new Error(msg || '未认证'))\n }\n if (code === BizCode.Forbidden || code === BizCode.PermissionDenied) {\n if (!response.config.silent) message.warning('暂无权限访问')\n return Promise.reject(new Error(msg || '暂无权限'))\n }\n if (!response.config.silent) message.error(msg || '请求失败')\n return Promise.reject(new Error(msg || '请求失败'))\n },\n async (error: AxiosError) => {\n if (error.response?.status === 401) {\n handleSessionExpired()\n return Promise.reject(error)\n }\n const data = error.response?.data as any\n if (!error.config?.silent) message.error(data?.msg || '请求失败')\n return Promise.reject(error)\n },\n )\n return instance\n}\n\nfunction handleSessionExpired() {\n // 先清本地 user(避免刷新后 sessionStorage 残留导致 401 循环),再跳转登录。\n sessionExpiredHandler?.()\n window.location.href = '/'\n}\n\n/**\n * createApiClient 创建一个独立配置的业务 API 客户端(axios 实例)。\n * 外部接入方用它指定自己的 baseURL(外部应用通常不带 /v1 前缀或指向别的域)。\n * 401/令牌失效、权限、业务错误的拦截逻辑与仓内默认实例完全一致。\n */\nexport function createApiClient(opts: CreateApiClientOptions = {}): AxiosInstance {\n const instance = axios.create({\n baseURL: opts.baseURL ?? '/v1',\n timeout: opts.timeout ?? 30000,\n headers: opts.headers,\n })\n return attachInterceptors(instance)\n}\n\n// 默认实例:供仓内(与 IAM 同源、API 挂在 /v1 下)的应用直接使用。\nconst request = createApiClient()\n\nexport default request\n","import { useEffect } from 'react'\nimport type { AuthContextProps } from 'react-oidc-context'\n\n/**\n * SSO 会话探活:监听 silent renew 失败,SSO 会话失效(其他端点全局登出)时\n * 清除本地 user,实现\"一处登出、处处登出\"(在 token 自动续期时生效)。\n *\n * 注意:不要通过主动调用 auth.signinSilent() 做轮询探活。实测在当前后端\n * (SP 拥有 refresh_token)下,每次 signinSilent 都会刷新 user 并触发\n * isAuthenticated 翻转 → 组件重载 → 再次探活,形成每数百毫秒一次的自激\n * renew 循环,导致页面周期性白屏;ref 无法阻断(翻转伴随 remount 重置)。\n * 因此这里仅以 silent renew 失败事件兜底登出,token 自动续期交给\n * `automaticSilentRenew`。\n */\nexport function useSSOSessionProbe(auth: AuthContextProps) {\n useEffect(() => {\n if (!auth.events?.addSilentRenewError) return\n const unsub = auth.events.addSilentRenewError(() => {\n void auth.removeUser()\n })\n return unsub\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [auth.events])\n}\n","import request from '../request'\nimport type {\n MyTenantsResp,\n PersonDetailResp,\n PersonUpdatePasswordReq,\n SessionListResp,\n UserinfoResp,\n} from '@ark-iam/types'\n\nexport const getUserinfo = () => request.get<any, UserinfoResp>('/auth/userinfo')\nexport const getMyTenants = () => request.get<any, MyTenantsResp>('/auth/me/tenants')\nexport const logoutAPI = (refreshToken: string) => request.post<any, void>('/auth/logout', { refreshToken })\nexport const logoutAllAPI = (refreshToken: string) => request.post<any, void>('/auth/logoutAll', { refreshToken })\nexport const getPersonDetail = () => request.get<any, PersonDetailResp>('/auth/me')\nexport const updatePassword = (req: PersonUpdatePasswordReq) => request.post<any, void>('/auth/me/changePassword', req)\nexport const getSessionList = (params?: { page?: number; pageSize?: number }) =>\n request.get<any, SessionListResp>('/auth/me/sessions', { params })\nexport const revokeSession = (sessionID: string) => request.delete<any, void>(`/auth/me/sessions/${sessionID}`)\nexport const revokeAllSessions = () => request.delete<any, void>('/auth/me/sessions')\n","import type { AxiosRequestConfig } from 'axios'\n\nimport request from '../request'\nimport type {\n ApplicationCreateReq,\n ApplicationItem,\n ApplicationUpdateReq,\n DomainItem,\n DomainVerificationStatus,\n MenuItem,\n MenuMyTreeResp,\n MenuTreeResp,\n OAuthClientCreateReq,\n OAuthClientDetail,\n OAuthClientItem,\n OAuthClientUpdateReq,\n OAuthSecretCreateResp,\n OAuthSecretItem,\n PageListResp,\n TenantApplicationCreateReq,\n TenantApplicationItem,\n TenantApplicationUpdateReq,\n TenantAdminResetPasswordResp,\n TenantCreateReq,\n TenantCreateResp,\n TenantItem,\n TenantStatus,\n TenantUpdateReq,\n} from '@ark-iam/types'\n\n// 用户与角色无平台端接口:两者按租户归属,读写与成员管理统一收敛到 /tenant/* (见 tenant-admin-web/src/api)。\n// 平台侧仅保留跨租户的「监督/干预」类只读或状态接口:租户、租户应用。\n\n// ==================== 应用 ====================\nexport const getApplicationPageList = (data: { page: number; pageSize: number; name?: string }) =>\n request.get<any, PageListResp<ApplicationItem>>('/platform/applications', { params: data })\n// config 用于传递 silent 等请求级选项:菜单页首屏恢复\"上次选择的应用\"属 best-effort 探测,\n// 应用已被删除/换库(旧 ID 失效)时静默回退,不弹全局提示(见 request.ts 的 silent)。\nexport const getApplicationDetail = (appID: string, config?: AxiosRequestConfig) =>\n request.get<any, ApplicationItem>(`/platform/applications/${appID}`, config)\nexport const createApplication = (data: ApplicationCreateReq) => request.post<any, { appID: string; code: string }>('/platform/applications', data)\nexport const updateApplication = (data: ApplicationUpdateReq) => {\n const { appID, ...body } = data\n return request.put<any, string>(`/platform/applications/${appID}`, body)\n}\nexport const deleteApplication = (appID: string) => request.delete<any, string>(`/platform/applications/${appID}`)\n\n// ==================== OAuth 客户端 ====================\nexport const getOAuthClientPageList = (data: { page: number; pageSize: number; name?: string }) =>\n request.get<any, PageListResp<OAuthClientItem>>('/platform/application-clients', { params: data })\nexport const getOAuthClientDetail = (applicationClientID: string) =>\n request.get<any, OAuthClientDetail>(`/platform/application-clients/${applicationClientID}`)\nexport const createOAuthClient = (data: OAuthClientCreateReq) =>\n request.post<any, { applicationClientID: string; code: string }>('/platform/application-clients', data)\nexport const updateOAuthClient = (data: OAuthClientUpdateReq) => {\n const { applicationClientID, ...body } = data\n return request.put<any, string>(`/platform/application-clients/${applicationClientID}`, body)\n}\nexport const deleteOAuthClient = (applicationClientID: string) =>\n request.delete<any, string>(`/platform/application-clients/${applicationClientID}`)\nexport const listOAuthSecrets = (applicationClientID: string) =>\n request.get<any, { total: number; secrets: OAuthSecretItem[] }>(`/platform/application-clients/${applicationClientID}/secrets`)\nexport const createOAuthSecret = (data: { applicationClientID: string; name: string; expiresAt?: number }) => {\n const { applicationClientID, ...body } = data\n return request.post<any, OAuthSecretCreateResp>(`/platform/application-clients/${applicationClientID}/secrets`, body)\n}\nexport const deleteOAuthSecret = (applicationClientID: string, secretID: string) =>\n request.delete<any, string>(`/platform/application-clients/${applicationClientID}/secrets/${secretID}`)\n\n// ==================== 租户 ====================\nexport const getTenantPageList = (data: { page: number; pageSize: number; name?: string; status?: TenantStatus }) =>\n request.get<any, PageListResp<TenantItem>>('/platform/tenants', { params: data })\nexport const createTenant = (data: TenantCreateReq) => request.post<any, TenantCreateResp>('/platform/tenants', data)\n/** 重置租户内置管理员(source=builtin)密码:新临时密码仅此一次返回;不作用于租户手工创建的成员 */\nexport const resetTenantAdminPassword = (tenantID: string) =>\n request.post<any, TenantAdminResetPasswordResp>(`/platform/tenants/${tenantID}/builtin-admin/reset-password`)\nexport const updateTenant = (data: TenantUpdateReq) => {\n const { tenantID, ...body } = data\n return request.put<any, string>(`/platform/tenants/${tenantID}`, body)\n}\nexport const deleteTenant = (tenantID: string) => request.delete<any, string>(`/platform/tenants/${tenantID}`)\n\n// ==================== 租户应用 ====================\nexport const getTenantApplicationPageList = (data: { page: number; pageSize: number; tenantID?: string; status?: string }) =>\n request.get<any, PageListResp<TenantApplicationItem>>('/platform/tenant-applications', { params: data })\nexport const createTenantApplication = (data: TenantApplicationCreateReq) =>\n request.post<any, { tenantAppID: string }>('/platform/tenant-applications', data)\nexport const updateTenantApplication = (data: TenantApplicationUpdateReq) => {\n const { tenantAppID, ...body } = data\n return request.put<any, string>(`/platform/tenant-applications/${tenantAppID}`, body)\n}\nexport const deleteTenantApplication = (tenantAppID: string) =>\n request.delete<any, string>(`/platform/tenant-applications/${tenantAppID}`)\n\n// ==================== 菜单 ====================\nexport const getMenuTree = (appID: string) => request.get<any, MenuTreeResp>('/platform/menus/tree', { params: { appID } })\nexport const getMyMenuTree = () => request.get<any, MenuMyTreeResp>('/platform/menus/my')\nexport const createMenu = (data: Partial<MenuItem>) => request.post<any, { menuID: string }>('/platform/menus', data)\nexport const updateMenu = (data: Partial<MenuItem>) => {\n const { menuID, ...body } = data\n return request.put<any, string>(`/platform/menus/${menuID}`, body)\n}\nexport const deleteMenu = (menuID: string) => request.delete<any, string>(`/platform/menus/${menuID}`)\n\n// ==================== 域名 ====================\nexport const getDomainPageList = (data: { page: number; pageSize: number; domain?: string }) =>\n request.get<any, PageListResp<DomainItem>>('/platform/domains', { params: data })\nexport const getDomainDetail = (id: string) => request.get<any, DomainItem>(`/platform/domains/${id}`)\nexport const createDomain = (domain: string) => request.post<any, { id: string }>('/platform/domains', { domain })\nexport const updateDomain = (data: { id: string; domain?: string; verificationStatus?: DomainVerificationStatus }) => {\n const { id, ...body } = data\n return request.put<any, string>(`/platform/domains/${id}`, body)\n}\nexport const deleteDomain = (id: string) => request.delete<any, string>(`/platform/domains/${id}`)\n"],"names":[],"mappings":";;;;AAkBA,IAAI,eAA2E;AAK/E,IAAI,wBAA6C;AAE1C,SAAS,gBAAgB,UAA6D;AAC3F,iBAAe;AACjB;AAEO,SAAS,yBAAyB,SAAqB;AAC5D,0BAAwB;AAC1B;AAWA,SAAS,mBAAmB,UAAyB;AACnD,WAAS,aAAa,QAAQ,IAAI,CAAC,WAAuC;AACxE,UAAM,OAAO;AACb,SAAI,6BAAM,iBAAgB,OAAO,SAAS;AACxC,aAAO,QAAQ,gBAAgB,UAAU,KAAK,YAAY;AAAA,IAC5D;AACA,WAAO;AAAA,EACT,CAAC;AAED,WAAS,aAAa,SAAS;AAAA,IAC7B,CAAC,aAAa;;AACZ,YAAM,EAAE,MAAM,IAAA,IAAQ,SAAS;AAC/B,UAAI,SAAS,QAAQ,QAAS,QAAO,SAAS,KAAK;AAEnD,YAAM,mBAAkB,cAAS,OAAO,QAAhB,mBAAqB,SAAS;AAEtD,UAAI,SAAS,QAAQ,gBAAgB,SAAS,QAAQ,gBAAgB,SAAS,QAAQ,cAAc;AACnG,YAAI,wBAAwB,QAAQ,OAAO,IAAI,MAAM,OAAO,iBAAiB,CAAC;AAC9E,6BAAA;AACA,eAAO,QAAQ,OAAO,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC/C;AACA,UAAI,SAAS,QAAQ,aAAa,SAAS,QAAQ,kBAAkB;AACnE,YAAI,CAAC,SAAS,OAAO,OAAQ,SAAQ,QAAQ,QAAQ;AACrD,eAAO,QAAQ,OAAO,IAAI,MAAM,OAAO,MAAM,CAAC;AAAA,MAChD;AACA,UAAI,CAAC,SAAS,OAAO,OAAQ,SAAQ,MAAM,OAAO,MAAM;AACxD,aAAO,QAAQ,OAAO,IAAI,MAAM,OAAO,MAAM,CAAC;AAAA,IAChD;AAAA,IACA,OAAO,UAAsB;;AAC3B,YAAI,WAAM,aAAN,mBAAgB,YAAW,KAAK;AAClC,6BAAA;AACA,eAAO,QAAQ,OAAO,KAAK;AAAA,MAC7B;AACA,YAAM,QAAO,WAAM,aAAN,mBAAgB;AAC7B,UAAI,GAAC,WAAM,WAAN,mBAAc,iBAAgB,OAAM,6BAAM,QAAO,MAAM;AAC5D,aAAO,QAAQ,OAAO,KAAK;AAAA,IAC7B;AAAA,EAAA;AAEF,SAAO;AACT;AAEA,SAAS,uBAAuB;AAE9B;AACA,SAAO,SAAS,OAAO;AACzB;AAOO,SAAS,gBAAgB,OAA+B,IAAmB;AAChF,QAAM,WAAW,MAAM,OAAO;AAAA,IAC5B,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK;AAAA,EAAA,CACf;AACD,SAAO,mBAAmB,QAAQ;AACpC;AAGA,MAAM,UAAU,gBAAA;AC1FT,SAAS,mBAAmB,MAAwB;AACzD,YAAU,MAAM;;AACd,QAAI,GAAC,UAAK,WAAL,mBAAa,qBAAqB;AACvC,UAAM,QAAQ,KAAK,OAAO,oBAAoB,MAAM;AAClD,WAAK,KAAK,WAAA;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EAET,GAAG,CAAC,KAAK,MAAM,CAAC;AAClB;ACdO,MAAM,cAAc,MAAM,QAAQ,IAAuB,gBAAgB;AACzE,MAAM,eAAe,MAAM,QAAQ,IAAwB,kBAAkB;AAC7E,MAAM,YAAY,CAAC,iBAAyB,QAAQ,KAAgB,gBAAgB,EAAE,cAAc;AACpG,MAAM,eAAe,CAAC,iBAAyB,QAAQ,KAAgB,mBAAmB,EAAE,cAAc;AAC1G,MAAM,kBAAkB,MAAM,QAAQ,IAA2B,UAAU;AAC3E,MAAM,iBAAiB,CAAC,QAAiC,QAAQ,KAAgB,2BAA2B,GAAG;AAC/G,MAAM,iBAAiB,CAAC,WAC7B,QAAQ,IAA0B,qBAAqB,EAAE,QAAQ;AAC5D,MAAM,gBAAgB,CAAC,cAAsB,QAAQ,OAAkB,qBAAqB,SAAS,EAAE;AACvG,MAAM,oBAAoB,MAAM,QAAQ,OAAkB,mBAAmB;ACgB7E,MAAM,yBAAyB,CAAC,SACrC,QAAQ,IAAwC,0BAA0B,EAAE,QAAQ,KAAA,CAAM;AAGrF,MAAM,uBAAuB,CAAC,OAAe,WAClD,QAAQ,IAA0B,0BAA0B,KAAK,IAAI,MAAM;AACtE,MAAM,oBAAoB,CAAC,SAA+B,QAAQ,KAA2C,0BAA0B,IAAI;AAC3I,MAAM,oBAAoB,CAAC,SAA+B;AAC/D,QAAM,EAAE,OAAO,GAAG,KAAA,IAAS;AAC3B,SAAO,QAAQ,IAAiB,0BAA0B,KAAK,IAAI,IAAI;AACzE;AACO,MAAM,oBAAoB,CAAC,UAAkB,QAAQ,OAAoB,0BAA0B,KAAK,EAAE;AAG1G,MAAM,yBAAyB,CAAC,SACrC,QAAQ,IAAwC,iCAAiC,EAAE,QAAQ,KAAA,CAAM;AAC5F,MAAM,uBAAuB,CAAC,wBACnC,QAAQ,IAA4B,iCAAiC,mBAAmB,EAAE;AACrF,MAAM,oBAAoB,CAAC,SAChC,QAAQ,KAAyD,iCAAiC,IAAI;AACjG,MAAM,oBAAoB,CAAC,SAA+B;AAC/D,QAAM,EAAE,qBAAqB,GAAG,KAAA,IAAS;AACzC,SAAO,QAAQ,IAAiB,iCAAiC,mBAAmB,IAAI,IAAI;AAC9F;AACO,MAAM,oBAAoB,CAAC,wBAChC,QAAQ,OAAoB,iCAAiC,mBAAmB,EAAE;AAC7E,MAAM,mBAAmB,CAAC,wBAC/B,QAAQ,IAAwD,iCAAiC,mBAAmB,UAAU;AACzH,MAAM,oBAAoB,CAAC,SAA4E;AAC5G,QAAM,EAAE,qBAAqB,GAAG,KAAA,IAAS;AACzC,SAAO,QAAQ,KAAiC,iCAAiC,mBAAmB,YAAY,IAAI;AACtH;AACO,MAAM,oBAAoB,CAAC,qBAA6B,aAC7D,QAAQ,OAAoB,iCAAiC,mBAAmB,YAAY,QAAQ,EAAE;AAGjG,MAAM,oBAAoB,CAAC,SAChC,QAAQ,IAAmC,qBAAqB,EAAE,QAAQ,KAAA,CAAM;AAC3E,MAAM,eAAe,CAAC,SAA0B,QAAQ,KAA4B,qBAAqB,IAAI;AAE7G,MAAM,2BAA2B,CAAC,aACvC,QAAQ,KAAwC,qBAAqB,QAAQ,+BAA+B;AACvG,MAAM,eAAe,CAAC,SAA0B;AACrD,QAAM,EAAE,UAAU,GAAG,KAAA,IAAS;AAC9B,SAAO,QAAQ,IAAiB,qBAAqB,QAAQ,IAAI,IAAI;AACvE;AACO,MAAM,eAAe,CAAC,aAAqB,QAAQ,OAAoB,qBAAqB,QAAQ,EAAE;AAGtG,MAAM,+BAA+B,CAAC,SAC3C,QAAQ,IAA8C,iCAAiC,EAAE,QAAQ,KAAA,CAAM;AAClG,MAAM,0BAA0B,CAAC,SACtC,QAAQ,KAAmC,iCAAiC,IAAI;AAC3E,MAAM,0BAA0B,CAAC,SAAqC;AAC3E,QAAM,EAAE,aAAa,GAAG,KAAA,IAAS;AACjC,SAAO,QAAQ,IAAiB,iCAAiC,WAAW,IAAI,IAAI;AACtF;AACO,MAAM,0BAA0B,CAAC,gBACtC,QAAQ,OAAoB,iCAAiC,WAAW,EAAE;AAGrE,MAAM,cAAc,CAAC,UAAkB,QAAQ,IAAuB,wBAAwB,EAAE,QAAQ,EAAE,QAAM,CAAG;AACnH,MAAM,gBAAgB,MAAM,QAAQ,IAAyB,oBAAoB;AACjF,MAAM,aAAa,CAAC,SAA4B,QAAQ,KAA8B,mBAAmB,IAAI;AAC7G,MAAM,aAAa,CAAC,SAA4B;AACrD,QAAM,EAAE,QAAQ,GAAG,KAAA,IAAS;AAC5B,SAAO,QAAQ,IAAiB,mBAAmB,MAAM,IAAI,IAAI;AACnE;AACO,MAAM,aAAa,CAAC,WAAmB,QAAQ,OAAoB,mBAAmB,MAAM,EAAE;AAG9F,MAAM,oBAAoB,CAAC,SAChC,QAAQ,IAAmC,qBAAqB,EAAE,QAAQ,KAAA,CAAM;AAC3E,MAAM,kBAAkB,CAAC,OAAe,QAAQ,IAAqB,qBAAqB,EAAE,EAAE;AAC9F,MAAM,eAAe,CAAC,WAAmB,QAAQ,KAA0B,qBAAqB,EAAE,QAAQ;AAC1G,MAAM,eAAe,CAAC,SAAyF;AACpH,QAAM,EAAE,IAAI,GAAG,KAAA,IAAS;AACxB,SAAO,QAAQ,IAAiB,qBAAqB,EAAE,IAAI,IAAI;AACjE;AACO,MAAM,eAAe,CAAC,OAAe,QAAQ,OAAoB,qBAAqB,EAAE,EAAE;"}
@@ -0,0 +1,34 @@
1
+ import { AxiosInstance } from 'axios';
2
+ /**
3
+ * silent:本次请求属于 best-effort 探测,失败由调用方自行兜底
4
+ * (典型场景:菜单页首屏恢复"上次选择的应用",该应用可能已被删除或换库,旧 ID 失效),
5
+ * 此时不弹全局提示,避免每次进页面都弹一个调用方已经处理掉的错误。
6
+ *
7
+ * 语义边界:silent 只抑制「提示」(message.error / message.warning);
8
+ * 401/令牌失效的会话处置(handleSessionExpired → 跳登录页)是流程控制,不受 silent 影响。
9
+ */
10
+ declare module 'axios' {
11
+ interface AxiosRequestConfig {
12
+ silent?: boolean;
13
+ }
14
+ }
15
+ export declare function setUserProvider(provider: () => {
16
+ access_token: string;
17
+ } | null | undefined): void;
18
+ export declare function setSessionExpiredHandler(handler: () => void): void;
19
+ export interface CreateApiClientOptions {
20
+ /** 业务 API 基址(含版本段),如 '/v1' 或 'https://iam.example.com/v1'。默认 '/v1'。 */
21
+ baseURL?: string;
22
+ /** 请求超时(毫秒),默认 30000。 */
23
+ timeout?: number;
24
+ /** 追加到每个请求的静态请求头。 */
25
+ headers?: Record<string, string>;
26
+ }
27
+ /**
28
+ * createApiClient 创建一个独立配置的业务 API 客户端(axios 实例)。
29
+ * 外部接入方用它指定自己的 baseURL(外部应用通常不带 /v1 前缀或指向别的域)。
30
+ * 401/令牌失效、权限、业务错误的拦截逻辑与仓内默认实例完全一致。
31
+ */
32
+ export declare function createApiClient(opts?: CreateApiClientOptions): AxiosInstance;
33
+ declare const request: AxiosInstance;
34
+ export default request;
@@ -0,0 +1,13 @@
1
+ import type { MyTenantsResp, PersonDetailResp, PersonUpdatePasswordReq, SessionListResp, UserinfoResp } from '../../types/index';
2
+ export declare const getUserinfo: () => Promise<UserinfoResp>;
3
+ export declare const getMyTenants: () => Promise<MyTenantsResp>;
4
+ export declare const logoutAPI: (refreshToken: string) => Promise<void>;
5
+ export declare const logoutAllAPI: (refreshToken: string) => Promise<void>;
6
+ export declare const getPersonDetail: () => Promise<PersonDetailResp>;
7
+ export declare const updatePassword: (req: PersonUpdatePasswordReq) => Promise<void>;
8
+ export declare const getSessionList: (params?: {
9
+ page?: number;
10
+ pageSize?: number;
11
+ }) => Promise<SessionListResp>;
12
+ export declare const revokeSession: (sessionID: string) => Promise<void>;
13
+ export declare const revokeAllSessions: () => Promise<void>;
@@ -0,0 +1,80 @@
1
+ import type { AxiosRequestConfig } from 'axios';
2
+ import type { ApplicationCreateReq, ApplicationItem, ApplicationUpdateReq, DomainItem, DomainVerificationStatus, MenuItem, MenuMyTreeResp, MenuTreeResp, OAuthClientCreateReq, OAuthClientDetail, OAuthClientItem, OAuthClientUpdateReq, OAuthSecretCreateResp, OAuthSecretItem, PageListResp, TenantApplicationCreateReq, TenantApplicationItem, TenantApplicationUpdateReq, TenantAdminResetPasswordResp, TenantCreateReq, TenantCreateResp, TenantItem, TenantStatus, TenantUpdateReq } from '../../types/index';
3
+ export declare const getApplicationPageList: (data: {
4
+ page: number;
5
+ pageSize: number;
6
+ name?: string;
7
+ }) => Promise<PageListResp<ApplicationItem>>;
8
+ export declare const getApplicationDetail: (appID: string, config?: AxiosRequestConfig) => Promise<ApplicationItem>;
9
+ export declare const createApplication: (data: ApplicationCreateReq) => Promise<{
10
+ appID: string;
11
+ code: string;
12
+ }>;
13
+ export declare const updateApplication: (data: ApplicationUpdateReq) => Promise<string>;
14
+ export declare const deleteApplication: (appID: string) => Promise<string>;
15
+ export declare const getOAuthClientPageList: (data: {
16
+ page: number;
17
+ pageSize: number;
18
+ name?: string;
19
+ }) => Promise<PageListResp<OAuthClientItem>>;
20
+ export declare const getOAuthClientDetail: (applicationClientID: string) => Promise<OAuthClientDetail>;
21
+ export declare const createOAuthClient: (data: OAuthClientCreateReq) => Promise<{
22
+ applicationClientID: string;
23
+ code: string;
24
+ }>;
25
+ export declare const updateOAuthClient: (data: OAuthClientUpdateReq) => Promise<string>;
26
+ export declare const deleteOAuthClient: (applicationClientID: string) => Promise<string>;
27
+ export declare const listOAuthSecrets: (applicationClientID: string) => Promise<{
28
+ total: number;
29
+ secrets: OAuthSecretItem[];
30
+ }>;
31
+ export declare const createOAuthSecret: (data: {
32
+ applicationClientID: string;
33
+ name: string;
34
+ expiresAt?: number;
35
+ }) => Promise<OAuthSecretCreateResp>;
36
+ export declare const deleteOAuthSecret: (applicationClientID: string, secretID: string) => Promise<string>;
37
+ export declare const getTenantPageList: (data: {
38
+ page: number;
39
+ pageSize: number;
40
+ name?: string;
41
+ status?: TenantStatus;
42
+ }) => Promise<PageListResp<TenantItem>>;
43
+ export declare const createTenant: (data: TenantCreateReq) => Promise<TenantCreateResp>;
44
+ /** 重置租户内置管理员(source=builtin)密码:新临时密码仅此一次返回;不作用于租户手工创建的成员 */
45
+ export declare const resetTenantAdminPassword: (tenantID: string) => Promise<TenantAdminResetPasswordResp>;
46
+ export declare const updateTenant: (data: TenantUpdateReq) => Promise<string>;
47
+ export declare const deleteTenant: (tenantID: string) => Promise<string>;
48
+ export declare const getTenantApplicationPageList: (data: {
49
+ page: number;
50
+ pageSize: number;
51
+ tenantID?: string;
52
+ status?: string;
53
+ }) => Promise<PageListResp<TenantApplicationItem>>;
54
+ export declare const createTenantApplication: (data: TenantApplicationCreateReq) => Promise<{
55
+ tenantAppID: string;
56
+ }>;
57
+ export declare const updateTenantApplication: (data: TenantApplicationUpdateReq) => Promise<string>;
58
+ export declare const deleteTenantApplication: (tenantAppID: string) => Promise<string>;
59
+ export declare const getMenuTree: (appID: string) => Promise<MenuTreeResp>;
60
+ export declare const getMyMenuTree: () => Promise<MenuMyTreeResp>;
61
+ export declare const createMenu: (data: Partial<MenuItem>) => Promise<{
62
+ menuID: string;
63
+ }>;
64
+ export declare const updateMenu: (data: Partial<MenuItem>) => Promise<string>;
65
+ export declare const deleteMenu: (menuID: string) => Promise<string>;
66
+ export declare const getDomainPageList: (data: {
67
+ page: number;
68
+ pageSize: number;
69
+ domain?: string;
70
+ }) => Promise<PageListResp<DomainItem>>;
71
+ export declare const getDomainDetail: (id: string) => Promise<DomainItem>;
72
+ export declare const createDomain: (domain: string) => Promise<{
73
+ id: string;
74
+ }>;
75
+ export declare const updateDomain: (data: {
76
+ id: string;
77
+ domain?: string;
78
+ verificationStatus?: DomainVerificationStatus;
79
+ }) => Promise<string>;
80
+ export declare const deleteDomain: (id: string) => Promise<string>;
@@ -0,0 +1,13 @@
1
+ import type { AuthContextProps } from 'react-oidc-context';
2
+ /**
3
+ * SSO 会话探活:监听 silent renew 失败,SSO 会话失效(其他端点全局登出)时
4
+ * 清除本地 user,实现"一处登出、处处登出"(在 token 自动续期时生效)。
5
+ *
6
+ * 注意:不要通过主动调用 auth.signinSilent() 做轮询探活。实测在当前后端
7
+ * (SP 拥有 refresh_token)下,每次 signinSilent 都会刷新 user 并触发
8
+ * isAuthenticated 翻转 → 组件重载 → 再次探活,形成每数百毫秒一次的自激
9
+ * renew 循环,导致页面周期性白屏;ref 无法阻断(翻转伴随 remount 重置)。
10
+ * 因此这里仅以 silent renew 失败事件兜底登出,token 自动续期交给
11
+ * `automaticSilentRenew`。
12
+ */
13
+ export declare function useSSOSessionProbe(auth: AuthContextProps): void;
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ export interface CreateAuthProviderOptions {
3
+ /**
4
+ * OIDC client_id(控制台应用的 application_client.code)。
5
+ * 未传时优先用 /config.json 的 clientId,再退回 import.meta.env.VITE_OIDC_CLIENT_ID。
6
+ */
7
+ clientID?: string;
8
+ clientSecret?: string;
9
+ /**
10
+ * OIDC issuer(OP 地址)。未传时优先级:/config.json.issuer > VITE_OIDC_ISSUER > '/oidc'。
11
+ * 多源部署时可显式传 OP 的绝对地址(如 https://iam.example.com/oidc)。
12
+ */
13
+ issuer?: string;
14
+ redirectPath?: string;
15
+ postLogoutRedirectPath?: string;
16
+ getExtraQueryParams?: () => Record<string, string | number | boolean>;
17
+ /**
18
+ * 是否在启动时拉取 `{base}/config.json` 作为运行时配置来源(默认 true)。
19
+ * 置 false 则完全走 props / VITE_* / 默认值,适用于无 IAM 托管 / 无 config.json 的场景。
20
+ */
21
+ useRuntimeConfig?: boolean;
22
+ /** config.json 的拉取基址;默认 import.meta.env.BASE_URL。 */
23
+ runtimeConfigBase?: string;
24
+ }
25
+ export declare function createAuthProvider(opts?: CreateAuthProviderOptions): ({ children }: {
26
+ children: React.ReactNode;
27
+ }) => React.JSX.Element | null;
@@ -0,0 +1,23 @@
1
+ export declare const defaultIssuer = "/oidc";
2
+ export declare const defaultRedirectPath = "/auth/callback";
3
+ export declare const defaultPostLogoutRedirectPath = "/login";
4
+ export declare const defaultScope = "openid profile email offline_access";
5
+ /**
6
+ * RuntimeConfig 是后端 /config.json 下发的运行时配置(见 backend/iam/app_frontend.go)。
7
+ * 字段全部可选:缺失时逐字段回退到 VITE_* / 相对默认值。
8
+ */
9
+ export interface RuntimeConfig {
10
+ issuer?: string;
11
+ apiBase?: string;
12
+ oidcBase?: string;
13
+ callbackPath?: string;
14
+ clientId?: string;
15
+ }
16
+ /**
17
+ * fetchRuntimeConfig 从 `{base}/config.json` 拉取运行时配置。
18
+ *
19
+ * - base 默认取 `import.meta.env.BASE_URL`(Vite 注入;自托管常为 '/'),保证子路径部署也能命中。
20
+ * - 任一环节失败(网络、非 2xx、非 JSON)都 resolve 为 null,由调用方回退默认值,绝不 reject,
21
+ * 避免因配置端点不可用而阻断整个应用启动。
22
+ */
23
+ export declare function fetchRuntimeConfig(base?: string): Promise<RuntimeConfig | null>;
@@ -0,0 +1 @@
1
+ export declare function FullPageSpinner(): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ export interface TenantSwitchInfo {
2
+ tenants: {
3
+ tenantID: string;
4
+ name: string;
5
+ }[];
6
+ loadTenants: () => Promise<void>;
7
+ handleSwitchTenant: (tenantID: string) => Promise<void>;
8
+ }
9
+ export declare function useTenantSwitching(): TenantSwitchInfo;
10
+ export declare function useLogout(): () => Promise<void>;
11
+ export declare function useAuthGuard(): import("react-oidc-context").AuthContextProps;
@@ -0,0 +1,8 @@
1
+ export { createAuthProvider } from './AuthProvider';
2
+ export type { CreateAuthProviderOptions } from './AuthProvider';
3
+ export { defaultIssuer, defaultRedirectPath, defaultPostLogoutRedirectPath, defaultScope, fetchRuntimeConfig, } from './config';
4
+ export type { RuntimeConfig } from './config';
5
+ export * from './tenant';
6
+ export { useTenantSwitching, useLogout, useAuthGuard } from './hooks';
7
+ export type { TenantSwitchInfo } from './hooks';
8
+ export { FullPageSpinner } from './guards';