@tsingroc/tsingroc-components 5.0.0-alpha.22 → 5.0.0-alpha.23

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.
@@ -13,8 +13,13 @@ export interface GenericAuthProviderProps extends SessionStoreOptions {
13
13
  persistent: false;
14
14
  children: ReactNode;
15
15
  }
16
- export declare function AuthProvider(props: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
16
+ /**
17
+ * 为内部的组件提供鉴权服务。{@linkcode useSessionStore} 和 {@linkcode useSession},
18
+ * 还有很多其它 hooks 和组件都只能在这个组件的内部使用。
19
+ */
20
+ export declare function AuthProvider(props: AuthProviderProps): ReactNode;
17
21
  export declare function useSessionStoreInternal(user: string): SessionStore;
22
+ /** 获取当前上下文的 {@linkcode SessionStore}。 */
18
23
  export declare const useSessionStore: () => SessionStore;
19
24
  export declare function useSessionInternal(user: string, allowNull?: false): Session;
20
25
  export declare function useSessionInternal(user: string, allowNull: true): Session | null;
@@ -25,5 +30,6 @@ export interface UseSessionOptions {
25
30
  export interface UseSessionNonNullableOptions extends UseSessionOptions {
26
31
  allowNull?: false;
27
32
  }
33
+ /** 获取当前上下文的登录会话。 */
28
34
  export declare function useSession(options?: UseSessionNonNullableOptions): Session;
29
35
  export declare function useSession(options?: UseSessionOptions): Session | null;
@@ -4,6 +4,10 @@ import { FetcherWithAuth } from "./Fetcher";
4
4
  import { SessionStore } from "./SessionStore";
5
5
  import { jsx as _jsx } from "react/jsx-runtime";
6
6
  const AuthContext = /*#__PURE__*/createContext(null);
7
+ /**
8
+ * 为内部的组件提供鉴权服务。{@linkcode useSessionStore} 和 {@linkcode useSession},
9
+ * 还有很多其它 hooks 和组件都只能在这个组件的内部使用。
10
+ */
7
11
  export function AuthProvider(props) {
8
12
  const $ = _c(14);
9
13
  let children;
@@ -71,6 +75,8 @@ export function useSessionStoreInternal(user) {
71
75
  }
72
76
  return sessionStore;
73
77
  }
78
+
79
+ /** 获取当前上下文的 {@linkcode SessionStore}。 */
74
80
  export const useSessionStore =
75
81
  //
76
82
  useSessionStoreInternal.bind(undefined, "useSessionStore");
@@ -103,6 +109,9 @@ export function useSessionInternal(user, t0) {
103
109
  }
104
110
  return session;
105
111
  }
112
+
113
+ /** 获取当前上下文的登录会话。 */
114
+
106
115
  export function useSession(t0) {
107
116
  const $ = _c(4);
108
117
  const options = t0 === undefined ? {} : t0;
@@ -1,5 +1,5 @@
1
1
  import type { SdkConfig } from "casdoor-js-sdk/lib/esm/sdk";
2
- import type { JwtPayload } from "jwt-decode";
2
+ import { type JwtPayload } from "jwt-decode";
3
3
  import { type ReactNode } from "react";
4
4
  import type { AuthService, UserInfo } from "./AuthService";
5
5
  import { fetcherWithBearerToken } from "./Fetcher";
@@ -8,6 +8,16 @@ export interface CasdoorAuthServiceOptions {
8
8
  signinOrigin?: string;
9
9
  signinPath?: string | undefined;
10
10
  }
11
+ /**
12
+ * 基于 Casdoor 的鉴权服务。该鉴权服务的登录流程如下:
13
+ *
14
+ * 1. 调用 {@linkcode CasdoorAuthService.getSession | getSession()} 跳转到 SSO 登录页面。
15
+ * 2. 用户在登录页面完成登录,跳转到回调页面。
16
+ * 3. 回调页面调用 {@linkcode CasdoorAuthService.callback | callback()} 获取 token。
17
+ *
18
+ * 当使用 {@linkcode AuthProvider} 时,第 1 步由 {@linkcode LoginCheck} 完成,
19
+ * 第 3 步由 {@linkcode CasdoorCallback} 完成。
20
+ */
11
21
  export declare class CasdoorAuthService implements AuthService<string, CasdoorUserInfo> {
12
22
  #private;
13
23
  constructor(options: CasdoorAuthServiceOptions);
@@ -20,8 +30,13 @@ export declare class CasdoorAuthService implements AuthService<string, CasdoorUs
20
30
  * 若用户不经过登录流程进入回调页面,或者后端发生错误,则会抛出异常。
21
31
  */
22
32
  callback(): Promise<string>;
23
- fetcherMiddleware: typeof fetcherWithBearerToken;
33
+ readonly fetcherMiddleware: typeof fetcherWithBearerToken;
24
34
  parseUserInfo(info: CasdoorUserInfo): UserInfo;
35
+ /**
36
+ * 解析 token 中的内容。
37
+ * Token 可以通过 `useSession().state` 获取。
38
+ */
39
+ decodeToken(token: string): CasdoorTokenPayload;
25
40
  }
26
41
  export interface CasdoorTokenPayload extends JwtPayload {
27
42
  /**
@@ -125,11 +140,13 @@ export interface CasdoorCallbackProps {
125
140
  */
126
141
  children?: ReactNode;
127
142
  }
128
- export declare function CasdoorCallback(props: CasdoorCallbackProps): string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null;
143
+ /** Casdoor 回调组件。请将该组件放置在 {@linkcode CasdoorAuthService} 中设定的回调路径上。 */
144
+ export declare function CasdoorCallback(props: CasdoorCallbackProps): ReactNode;
129
145
  export interface CasdoorRoleCheckProps {
130
146
  required: string[];
131
147
  forbidden?: string[];
132
148
  error?: ReactNode;
133
149
  children: ReactNode;
134
150
  }
151
+ /** 检查 Casdoor 用户的角色(role),限制只有特定角色的用户才能访问内部的组件。 */
135
152
  export declare function CasdoorRoleCheck(props: CasdoorRoleCheckProps): ReactNode;
@@ -1,9 +1,23 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
2
  import Sdk from "casdoor-js-sdk";
3
+ import { jwtDecode } from "jwt-decode";
3
4
  import { useEffect, useEffectEvent, useRef, useState, useSyncExternalStore } from "react";
4
- import { useSessionStoreInternal } from "./AuthProvider";
5
+ import { useSessionStoreInternal } from "./AuthProvider"; // oxlint-disable-line no-unused-vars
6
+
5
7
  import { EmbeddedAuthService } from "./EmbeddedAuth";
6
8
  import { fetcherWithBearerToken } from "./Fetcher";
9
+ // oxlint-disable-line no-unused-vars
10
+
11
+ /**
12
+ * 基于 Casdoor 的鉴权服务。该鉴权服务的登录流程如下:
13
+ *
14
+ * 1. 调用 {@linkcode CasdoorAuthService.getSession | getSession()} 跳转到 SSO 登录页面。
15
+ * 2. 用户在登录页面完成登录,跳转到回调页面。
16
+ * 3. 回调页面调用 {@linkcode CasdoorAuthService.callback | callback()} 获取 token。
17
+ *
18
+ * 当使用 {@linkcode AuthProvider} 时,第 1 步由 {@linkcode LoginCheck} 完成,
19
+ * 第 3 步由 {@linkcode CasdoorCallback} 完成。
20
+ */
7
21
  export class CasdoorAuthService {
8
22
  #sdk;
9
23
  #signinOrigin;
@@ -45,7 +59,16 @@ export class CasdoorAuthService {
45
59
  parseUserInfo(info) {
46
60
  return info;
47
61
  }
62
+
63
+ /**
64
+ * 解析 token 中的内容。
65
+ * Token 可以通过 `useSession().state` 获取。
66
+ */
67
+ decodeToken(token) {
68
+ return jwtDecode(token);
69
+ }
48
70
  }
71
+ /** Casdoor 回调组件。请将该组件放置在 {@linkcode CasdoorAuthService} 中设定的回调路径上。 */
49
72
  export function CasdoorCallback(props) {
50
73
  const $ = _c(8);
51
74
  const {
@@ -110,6 +133,7 @@ export function CasdoorCallback(props) {
110
133
  useEffect(t4, t5);
111
134
  return status === "loading" ? children : status === "error" ? error : success;
112
135
  }
136
+ /** 检查 Casdoor 用户的角色(role),限制只有特定角色的用户才能访问内部的组件。 */
113
137
  export function CasdoorRoleCheck(props) {
114
138
  const $ = _c(4);
115
139
  const {
@@ -1,16 +1,38 @@
1
1
  import type { SdkConfig } from "casdoor-js-sdk/lib/esm/sdk";
2
+ import { type IframeHTMLAttributes, type ReactNode, type RefAttributes } from "react";
2
3
  import type { AuthService, UserInfo } from "./AuthService";
3
- import type { CasdoorUserInfo } from "./CasdoorAuth";
4
+ import { type CasdoorTokenPayload, type CasdoorUserInfo } from "./CasdoorAuth";
4
5
  import { fetcherWithBearerToken } from "./Fetcher";
5
6
  export interface EmbeddedAuthServiceOptions {
6
7
  config: SdkConfig;
7
8
  timeout?: number;
8
9
  }
10
+ /**
11
+ * 嵌入式鉴权服务,只能在 iframe 内使用。该鉴权服务的登录流程如下:
12
+ *
13
+ * 1. 调用 {@linkcode EmbeddedAuthService.getSession | getSession()} 向父页面获取 token。
14
+ * 2. 父页面响应请求,提供 token。
15
+ * 3. {@linkcode EmbeddedAuthService.getSession | getSession()} 返回 token。
16
+ *
17
+ * 当使用 {@linkcode AuthProvider} 时,第 1、3 步由 {@linkcode LoginCheck} 完成,
18
+ * 第 2 步由父页面中的 {@linkcode Embed} 完成。
19
+ */
9
20
  export declare class EmbeddedAuthService implements AuthService<string, CasdoorUserInfo> {
10
21
  #private;
11
22
  constructor(options: EmbeddedAuthServiceOptions);
12
23
  getSession(): Promise<string>;
13
24
  validate(token: string): Promise<CasdoorUserInfo>;
14
- fetcherMiddleware: typeof fetcherWithBearerToken;
25
+ readonly fetcherMiddleware: typeof fetcherWithBearerToken;
15
26
  parseUserInfo(info: CasdoorUserInfo): UserInfo;
27
+ /**
28
+ * 解析 token 中的内容。
29
+ * Token 可以通过 `useSession().state` 获取。
30
+ */
31
+ decodeToken(token: string): CasdoorTokenPayload;
16
32
  }
33
+ /**
34
+ * 嵌入一个使用了 {@linkcode EmbeddedAuthService} 的页面。
35
+ * 该组件必须搭配 {@linkcode CasdoorAuthService} 或 {@linkcode EmbeddedAuthService},并且在 {@linkcode LoginCheck} 内部使用。
36
+ * 该组件只负责向子页面提供 token,其它方面的用法和 `<iframe>` 完全相同。
37
+ */
38
+ export declare function Embed(props: IframeHTMLAttributes<HTMLIFrameElement> & RefAttributes<HTMLIFrameElement>): ReactNode;
@@ -1,5 +1,23 @@
1
+ import { c as _c } from "react/compiler-runtime";
1
2
  import Sdk from "casdoor-js-sdk";
3
+ import { jwtDecode } from "jwt-decode";
4
+ import { useEffectEvent, useSyncExternalStore } from "react";
5
+ import { useSessionStoreInternal } from "./AuthProvider"; // oxlint-disable-line no-unused-vars
6
+
7
+ import { CasdoorAuthService } from "./CasdoorAuth";
2
8
  import { fetcherWithBearerToken } from "./Fetcher";
9
+ // oxlint-disable-line no-unused-vars
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ /**
12
+ * 嵌入式鉴权服务,只能在 iframe 内使用。该鉴权服务的登录流程如下:
13
+ *
14
+ * 1. 调用 {@linkcode EmbeddedAuthService.getSession | getSession()} 向父页面获取 token。
15
+ * 2. 父页面响应请求,提供 token。
16
+ * 3. {@linkcode EmbeddedAuthService.getSession | getSession()} 返回 token。
17
+ *
18
+ * 当使用 {@linkcode AuthProvider} 时,第 1、3 步由 {@linkcode LoginCheck} 完成,
19
+ * 第 2 步由父页面中的 {@linkcode Embed} 完成。
20
+ */
3
21
  export class EmbeddedAuthService {
4
22
  #sdk;
5
23
  #timeout;
@@ -50,4 +68,138 @@ export class EmbeddedAuthService {
50
68
  parseUserInfo(info) {
51
69
  return info;
52
70
  }
71
+
72
+ /**
73
+ * 解析 token 中的内容。
74
+ * Token 可以通过 `useSession().state` 获取。
75
+ */
76
+ decodeToken(token) {
77
+ return jwtDecode(token);
78
+ }
79
+ }
80
+
81
+ /**
82
+ * 嵌入一个使用了 {@linkcode EmbeddedAuthService} 的页面。
83
+ * 该组件必须搭配 {@linkcode CasdoorAuthService} 或 {@linkcode EmbeddedAuthService},并且在 {@linkcode LoginCheck} 内部使用。
84
+ * 该组件只负责向子页面提供 token,其它方面的用法和 `<iframe>` 完全相同。
85
+ */
86
+ export function Embed(props) {
87
+ const $ = _c(16);
88
+ const sessionStore = useSessionStoreInternal("useSession");
89
+ if (!(sessionStore.service instanceof CasdoorAuthService || sessionStore.service instanceof EmbeddedAuthService)) {
90
+ throw new Error("CasdoorRoleCheck \u5FC5\u987B\u642D\u914D CasdoorAuthService \u6216 EmbeddedAuthService \u4F7F\u7528\uFF01");
91
+ }
92
+ let t0;
93
+ if ($[0] !== sessionStore) {
94
+ t0 = onChange => {
95
+ sessionStore.addEventListener(onChange);
96
+ return () => sessionStore.addEventListener(onChange);
97
+ };
98
+ $[0] = sessionStore;
99
+ $[1] = t0;
100
+ } else {
101
+ t0 = $[1];
102
+ }
103
+ let t1;
104
+ if ($[2] !== sessionStore.session) {
105
+ t1 = () => sessionStore.session;
106
+ $[2] = sessionStore.session;
107
+ $[3] = t1;
108
+ } else {
109
+ t1 = $[3];
110
+ }
111
+ const session = useSyncExternalStore(t0, t1);
112
+ if (!session) {
113
+ throw new Error("\u5F53\u524D\u7528\u6237\u672A\u767B\u5F55\uFF0C\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8BDD\u3002\u8BF7\u786E\u4FDD\u53EA\u5728 LoginCheck \u5185\u90E8\u4F7F\u7528 Embed\u3002");
114
+ }
115
+ const {
116
+ state: token
117
+ } = session;
118
+ let t2;
119
+ if ($[4] !== props.src || $[5] !== token) {
120
+ t2 = (event, elem) => {
121
+ if (!props.src) {
122
+ return;
123
+ }
124
+ if (event.source !== elem.contentWindow) {
125
+ return;
126
+ }
127
+ const data = event.data;
128
+ if (typeof data !== "object" || !data || !("type" in data) || typeof data.type !== "string") {
129
+ return;
130
+ }
131
+ if (data.type === "REQUEST_TOKEN") {
132
+ elem.contentWindow?.postMessage({
133
+ type: "TOKEN_RESPONSE",
134
+ token
135
+ }, new URL(props.src).origin);
136
+ }
137
+ };
138
+ $[4] = props.src;
139
+ $[5] = token;
140
+ $[6] = t2;
141
+ } else {
142
+ t2 = $[6];
143
+ }
144
+ const onMessage = useEffectEvent(t2);
145
+ let ref;
146
+ let rest;
147
+ if ($[7] !== props) {
148
+ ({
149
+ ref,
150
+ ...rest
151
+ } = props);
152
+ $[7] = props;
153
+ $[8] = ref;
154
+ $[9] = rest;
155
+ } else {
156
+ ref = $[8];
157
+ rest = $[9];
158
+ }
159
+ let t3;
160
+ if ($[10] !== onMessage || $[11] !== ref) {
161
+ t3 = elem_0 => {
162
+ if (!elem_0) {
163
+ return;
164
+ }
165
+ const listener = event_0 => onMessage(event_0, elem_0);
166
+ window.addEventListener("message", listener);
167
+ let cleanup = undefined;
168
+ if (typeof ref === "function") {
169
+ const cleanupOrUndefined = ref(elem_0);
170
+ if (typeof cleanupOrUndefined === "function") {
171
+ cleanup = cleanupOrUndefined;
172
+ } else {
173
+ cleanup = () => ref(null);
174
+ }
175
+ } else {
176
+ if (ref) {
177
+ ref.current = elem_0;
178
+ cleanup = () => ref.current = null;
179
+ }
180
+ }
181
+ return () => {
182
+ cleanup?.();
183
+ window.removeEventListener("message", listener);
184
+ };
185
+ };
186
+ $[10] = onMessage;
187
+ $[11] = ref;
188
+ $[12] = t3;
189
+ } else {
190
+ t3 = $[12];
191
+ }
192
+ let t4;
193
+ if ($[13] !== rest || $[14] !== t3) {
194
+ t4 = /*#__PURE__*/_jsx("iframe", {
195
+ ref: t3,
196
+ ...rest
197
+ });
198
+ $[13] = rest;
199
+ $[14] = t3;
200
+ $[15] = t4;
201
+ } else {
202
+ t4 = $[15];
203
+ }
204
+ return t4;
53
205
  }
@@ -16,15 +16,23 @@ export type Fetcher = (resource: RequestInfo | URL, options?: RequestInit & Fetc
16
16
  export interface FetcherExtraOptions {
17
17
  loginOn401?: boolean;
18
18
  }
19
+ /** 在请求中添加 Authorization 头的 fetcher 中间件。 */
19
20
  export declare function fetcherWithBearerToken(token: string): (fetcher: Fetcher) => Fetcher;
21
+ /** 在请求返回 401 错误时自动尝试登录的 fetcher 中间件。 */
20
22
  export declare function fetcherWithLoginOn401(sessionStore: SessionStore): (fetcher: Fetcher) => Fetcher;
23
+ /** 获取当前上下文的 fetcher。 */
21
24
  export declare function useFetcher(): Fetcher;
22
25
  export interface FetcherMiddlewareProps {
23
26
  middleware: (fetcher: Fetcher) => Fetcher;
24
27
  children: ReactNode;
25
28
  }
26
- export declare function FetcherMiddleware(props: FetcherMiddlewareProps): import("react/jsx-runtime").JSX.Element;
29
+ /** 为内部的组件添加额外的 fetcher 中间件,例如在发生错误时弹出警告。 */
30
+ export declare function FetcherMiddleware(props: FetcherMiddlewareProps): ReactNode;
27
31
  export interface FetcherWithAuthProps {
28
32
  children: ReactNode;
29
33
  }
30
- export declare function FetcherWithAuth(props: FetcherWithAuthProps): import("react/jsx-runtime").JSX.Element;
34
+ /**
35
+ * 为内部的组件的 fetcher 添加 Authorization 头。
36
+ * 默认设置下,{@linkcode AuthProvider} 已经提供了这个中间件,不需要另外添加。
37
+ */
38
+ export declare function FetcherWithAuth(props: FetcherWithAuthProps): ReactNode;
@@ -1,6 +1,6 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
2
  import { createContext, use, useSyncExternalStore } from "react";
3
- import { useSessionStoreInternal } from "./AuthProvider";
3
+ import { useSessionStoreInternal } from "./AuthProvider"; // oxlint-disable-line no-unused-vars
4
4
 
5
5
  /** 一个与 {@linkcode fetch} 兼容的 fetcher 函数 */
6
6
 
@@ -16,6 +16,7 @@ import { useSessionStoreInternal } from "./AuthProvider";
16
16
  * ```
17
17
  */
18
18
  import { jsx as _jsx } from "react/jsx-runtime";
19
+ /** 在请求中添加 Authorization 头的 fetcher 中间件。 */
19
20
  export function fetcherWithBearerToken(token) {
20
21
  return fetcher => async (resource, options) => {
21
22
  const headers = new Headers(options?.headers);
@@ -29,6 +30,8 @@ export function fetcherWithBearerToken(token) {
29
30
  return resp;
30
31
  };
31
32
  }
33
+
34
+ /** 在请求返回 401 错误时自动尝试登录的 fetcher 中间件。 */
32
35
  export function fetcherWithLoginOn401(sessionStore) {
33
36
  return fetcher => async (resource, options) => {
34
37
  const loggedIn = !!sessionStore.session;
@@ -42,9 +45,12 @@ export function fetcherWithLoginOn401(sessionStore) {
42
45
  };
43
46
  }
44
47
  const FetcherContext = /*#__PURE__*/createContext(fetch);
48
+
49
+ /** 获取当前上下文的 fetcher。 */
45
50
  export function useFetcher() {
46
51
  return use(FetcherContext);
47
52
  }
53
+ /** 为内部的组件添加额外的 fetcher 中间件,例如在发生错误时弹出警告。 */
48
54
  export function FetcherMiddleware(props) {
49
55
  const $ = _c(6);
50
56
  const {
@@ -75,6 +81,10 @@ export function FetcherMiddleware(props) {
75
81
  }
76
82
  return t1;
77
83
  }
84
+ /**
85
+ * 为内部的组件的 fetcher 添加 Authorization 头。
86
+ * 默认设置下,{@linkcode AuthProvider} 已经提供了这个中间件,不需要另外添加。
87
+ */
78
88
  export function FetcherWithAuth(props) {
79
89
  const $ = _c(12);
80
90
  const {
@@ -1,4 +1,4 @@
1
- import type { JwtPayload } from "jwt-decode";
1
+ import { type JwtPayload } from "jwt-decode";
2
2
  import type { AuthService, UserInfo } from "./AuthService";
3
3
  import { fetcherWithBearerToken } from "./Fetcher";
4
4
  export interface LocalAuthServiceOptions {
@@ -6,6 +6,17 @@ export interface LocalAuthServiceOptions {
6
6
  signinOrigin?: string;
7
7
  signinPath?: string;
8
8
  }
9
+ /**
10
+ * 用于内网使用的鉴权服务,目前只有风功率预测系统在使用这个鉴权服务。该鉴权服务的登录流程如下:
11
+ *
12
+ * 1. 调用 {@linkcode LocalAuthService.getSession | getSession()} 跳转到登录页面。
13
+ * 这个操作的具体实现由初始化时的设置项 {@linkcode LocalAuthServiceOptions.openLoginPage | openLoginPage} 提供。
14
+ * 用户需要自行实现跳转操作,可以直接修改 {@linkcode window.location},也可以使用 router 提供的导航功能。
15
+ * 2. 用户在登录页面输入账号密码,调用 {@linkcode LocalAuthService.login | login()} 得到 token。
16
+ *
17
+ * 当使用 {@linkcode AuthProvider} 时,第 1 步会由 {@linkcode LoginCheck} 自动调用,
18
+ * 第 2 步可以通过 {@linkcode useLocalLogin} 获取到登录函数。
19
+ */
9
20
  export declare class LocalAuthService implements AuthService<string, LocalUserInfo> {
10
21
  #private;
11
22
  constructor(options: LocalAuthServiceOptions);
@@ -18,8 +29,13 @@ export declare class LocalAuthService implements AuthService<string, LocalUserIn
18
29
  * 若账号密码错误,或者后端发生错误,则会抛出异常。
19
30
  */
20
31
  login(username: string, password: string): Promise<string>;
21
- fetcherMiddleware: typeof fetcherWithBearerToken;
32
+ readonly fetcherMiddleware: typeof fetcherWithBearerToken;
22
33
  parseUserInfo(info: LocalUserInfo): UserInfo;
34
+ /**
35
+ * 解析 token 中的内容。
36
+ * Token 可以通过 `useSession().state` 获取。
37
+ */
38
+ decodeToken(token: string): LocalTokenPayload;
23
39
  }
24
40
  export interface LocalTokenPayload extends JwtPayload {
25
41
  /** Token 的过期时间(Unix 时间戳)。*/
@@ -67,4 +83,8 @@ export interface LocalUserInfo {
67
83
  /** 更新时间。*/
68
84
  updatedAt: string;
69
85
  }
86
+ /**
87
+ * 获取 {@linkcode LocalAuthService} 的登录函数。
88
+ * 返回的函数只负责使用账号密码登录并将得到的 token 存入 session store,用户需要自行实现登录完成后的跳转。
89
+ */
70
90
  export declare function useLocalLogin(): (username: string, password: string) => Promise<import("./SessionStore").Session>;
@@ -1,6 +1,21 @@
1
1
  import { c as _c } from "react/compiler-runtime";
2
- import { useSessionStoreInternal } from "./AuthProvider";
2
+ import { jwtDecode } from "jwt-decode";
3
+ import { useSessionStoreInternal } from "./AuthProvider"; // oxlint-disable-line no-unused-vars
4
+
3
5
  import { fetcherWithBearerToken } from "./Fetcher";
6
+ // oxlint-disable-line no-unused-vars
7
+
8
+ /**
9
+ * 用于内网使用的鉴权服务,目前只有风功率预测系统在使用这个鉴权服务。该鉴权服务的登录流程如下:
10
+ *
11
+ * 1. 调用 {@linkcode LocalAuthService.getSession | getSession()} 跳转到登录页面。
12
+ * 这个操作的具体实现由初始化时的设置项 {@linkcode LocalAuthServiceOptions.openLoginPage | openLoginPage} 提供。
13
+ * 用户需要自行实现跳转操作,可以直接修改 {@linkcode window.location},也可以使用 router 提供的导航功能。
14
+ * 2. 用户在登录页面输入账号密码,调用 {@linkcode LocalAuthService.login | login()} 得到 token。
15
+ *
16
+ * 当使用 {@linkcode AuthProvider} 时,第 1 步会由 {@linkcode LoginCheck} 自动调用,
17
+ * 第 2 步可以通过 {@linkcode useLocalLogin} 获取到登录函数。
18
+ */
4
19
  export class LocalAuthService {
5
20
  #openLoginPage;
6
21
  #signinOrigin;
@@ -63,7 +78,19 @@ export class LocalAuthService {
63
78
  name: info.displayName ?? info.username ?? "未命名用户"
64
79
  };
65
80
  }
81
+
82
+ /**
83
+ * 解析 token 中的内容。
84
+ * Token 可以通过 `useSession().state` 获取。
85
+ */
86
+ decodeToken(token) {
87
+ return jwtDecode(token);
88
+ }
66
89
  }
90
+ /**
91
+ * 获取 {@linkcode LocalAuthService} 的登录函数。
92
+ * 返回的函数只负责使用账号密码登录并将得到的 token 存入 session store,用户需要自行实现登录完成后的跳转。
93
+ */
67
94
  export function useLocalLogin() {
68
95
  const $ = _c(3);
69
96
  const sessionStore = useSessionStoreInternal("useLocalLogin");
@@ -10,4 +10,8 @@ export interface LoginCheckProps {
10
10
  failed?: ReactNode;
11
11
  children: ReactNode;
12
12
  }
13
+ /**
14
+ * 限制只有已登录用户才能访问内部的组件。
15
+ * 未登录用户在该组件渲染时会自动尝试登录,登录方式由当前上下文使用的鉴权服务实现决定。
16
+ */
13
17
  export declare function LoginCheck(props: LoginCheckProps): ReactNode;
@@ -1,5 +1,9 @@
1
1
  import { useEffect, useEffectEvent, useState, useSyncExternalStore } from "react";
2
2
  import { useSessionStoreInternal } from "./AuthProvider";
3
+ /**
4
+ * 限制只有已登录用户才能访问内部的组件。
5
+ * 未登录用户在该组件渲染时会自动尝试登录,登录方式由当前上下文使用的鉴权服务实现决定。
6
+ */
3
7
  export function LoginCheck(props) {
4
8
  const {
5
9
  onValidated,
@@ -15,6 +15,7 @@ export interface SessionStoreOptions {
15
15
  /** 是否在网络连接恢复时立即检查登录状态是否有效。 @default false */
16
16
  revalidateOnReconnect?: boolean;
17
17
  }
18
+ /** 负责储存登录会话状态,并提供会话状态持久化、自动检查会话有效性等功能。 */
18
19
  export declare class SessionStore {
19
20
  #private;
20
21
  get service(): AuthService<unknown, unknown>;
@@ -1,3 +1,4 @@
1
+ /** 负责储存登录会话状态,并提供会话状态持久化、自动检查会话有效性等功能。 */
1
2
  export class SessionStore {
2
3
  #service;
3
4
  #persistent;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { AuthProvider, useSessionStore, useSession, type AuthProviderProps, type TokenBasedAuthProviderProps, type GenericAuthProviderProps, type UseSessionOptions, type UseSessionNonNullableOptions, } from "./components/auth/AuthProvider";
2
2
  export type { AuthService, UserInfo } from "./components/auth/AuthService";
3
3
  export { CasdoorAuthService, CasdoorCallback, CasdoorRoleCheck, type CasdoorAuthServiceOptions, type CasdoorTokenPayload, type CasdoorUserInfo, type CasdoorCallbackProps, type CasdoorRoleCheckProps, } from "./components/auth/CasdoorAuth";
4
- export { EmbeddedAuthService, type EmbeddedAuthServiceOptions, } from "./components/auth/EmbeddedAuth";
4
+ export { EmbeddedAuthService, Embed, type EmbeddedAuthServiceOptions, } from "./components/auth/EmbeddedAuth";
5
5
  export { fetcherWithBearerToken, fetcherWithLoginOn401, useFetcher, FetcherMiddleware, FetcherWithAuth, type Fetcher, type FetcherExtraOptions, type FetcherMiddlewareProps, type FetcherWithAuthProps, } from "./components/auth/Fetcher";
6
6
  export { LocalAuthService, useLocalLogin, type LocalAuthServiceOptions, type LocalTokenPayload, type LocalUserInfo, } from "./components/auth/LocalAuth";
7
7
  export { LoginCheck, type LoginCheckProps } from "./components/auth/LoginCheck";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { AuthProvider, useSessionStore, useSession } from "./components/auth/AuthProvider";
2
2
  export { CasdoorAuthService, CasdoorCallback, CasdoorRoleCheck } from "./components/auth/CasdoorAuth";
3
- export { EmbeddedAuthService } from "./components/auth/EmbeddedAuth";
3
+ export { EmbeddedAuthService, Embed } from "./components/auth/EmbeddedAuth";
4
4
  export { fetcherWithBearerToken, fetcherWithLoginOn401, useFetcher, FetcherMiddleware, FetcherWithAuth } from "./components/auth/Fetcher";
5
5
  export { LocalAuthService, useLocalLogin } from "./components/auth/LocalAuth";
6
6
  export { LoginCheck } from "./components/auth/LoginCheck";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsingroc/tsingroc-components",
3
- "version": "5.0.0-alpha.22",
3
+ "version": "5.0.0-alpha.23",
4
4
  "author": "",
5
5
  "license": "ISC",
6
6
  "description": "",