@choiceform/shared-auth 0.1.12 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,19 +54,25 @@ import { adminClient, organizationClient } from "better-auth/client/plugins"
54
54
  export const auth = initAuth({
55
55
  baseURL: import.meta.env.VITE_AUTH_API_URL || "http://localhost:4320",
56
56
  tokenStorageKey: "auth-token",
57
- defaultRedirectAfterLogin: "/explore",
58
- signInPath: "/sign-in",
57
+ // 可选:如果你想自定义插件
59
58
  plugins: [adminClient(), organizationClient({ teams: { enabled: true } })],
60
59
  })
60
+
61
+ // 注意:导航相关配置已移至组件层面:
62
+ // - 登录成功后的导航:在 SignInPage 组件中通过 onAuthSuccess 回调处理
63
+ // - 未授权时的导航:在 ProtectedRoute 组件中通过 onUnauthorized 回调处理
64
+ // - 登出后的导航:在调用 signOut 时传入 redirectTo 参数
61
65
  ```
62
66
 
63
67
  ### 2. 在应用中使用
64
68
 
65
69
  ```typescript
66
70
  import { AuthSync, ProtectedRoute, useAuthInit } from "@choiceform/shared-auth"
71
+ import { useNavigate } from "react-router"
67
72
  import { auth } from "./lib/auth"
68
73
 
69
74
  function App() {
75
+ const navigate = useNavigate()
70
76
  useAuthInit(auth)
71
77
 
72
78
  return (
@@ -77,7 +83,10 @@ function App() {
77
83
  <Route
78
84
  path="/*"
79
85
  element={
80
- <ProtectedRoute auth={auth} signInPath="/sign-in">
86
+ <ProtectedRoute
87
+ auth={auth}
88
+ onUnauthorized={() => navigate("/sign-in", { replace: true })}
89
+ >
81
90
  <YourApp />
82
91
  </ProtectedRoute>
83
92
  }
@@ -92,17 +101,25 @@ function App() {
92
101
 
93
102
  ```typescript
94
103
  import { SignInPage } from "@choiceform/shared-auth"
104
+ import { useNavigate } from "react-router"
95
105
  import { auth } from "./lib/auth"
96
106
 
97
107
  function LoginPage() {
108
+ const navigate = useNavigate()
109
+
98
110
  return (
99
111
  <SignInPage
100
112
  auth={auth}
101
- logo={<YourLogo />}
102
113
  title="Your App Title"
103
114
  description="Your app description"
104
115
  provider="github"
105
- redirectAfterLogin="/dashboard"
116
+ redirectUrl="/dashboard"
117
+ onAuthSuccess={() => navigate("/dashboard")}
118
+ githubButton={(isSigningIn) => (
119
+ <button disabled={isSigningIn}>
120
+ {isSigningIn ? "Redirecting to GitHub..." : "Sign in with GitHub"}
121
+ </button>
122
+ )}
106
123
  />
107
124
  )
108
125
  }
@@ -118,9 +135,9 @@ function LoginPage() {
118
135
 
119
136
  - `baseURL`: Better Auth API 基础 URL(必需)
120
137
  - `tokenStorageKey?`: Token 存储的 localStorage key(默认: `'auth-token'`)
121
- - `defaultRedirectAfterLogin?`: 登录后默认跳转地址(默认: `'/explore'`)
122
- - `signInPath?`: 登录页面路径(默认: `'/sign-in'`)
123
- - `plugins?`: Better Auth 插件列表(默认包含 `adminClient()` 和 `organizationClient()`)
138
+ - `plugins?`: Better Auth 插件列表(默认包含 `organizationClient()`)
139
+ - ~~`defaultRedirectAfterLogin?`~~: (已废弃) 建议在 SignInPage 组件中通过 `redirectUrl` prop 传入
140
+ - ~~`signInPath?`~~: (已废弃) 建议在 ProtectedRoute 组件中通过 `onUnauthorized` 回调处理导航
124
141
 
125
142
  **返回:** `AuthInstance`
126
143
 
@@ -132,11 +149,11 @@ function LoginPage() {
132
149
 
133
150
  - `baseURL`: Better Auth API 基础 URL(必需)
134
151
  - `tokenStorageKey?`: Token 存储的 localStorage key(默认: `'auth-token'`)
135
- - `defaultRedirectAfterLogin?`: 登录后默认跳转地址(默认: `'/explore'`)
136
- - `signInPath?`: 登录页面路径(默认: `'/sign-in'`)
137
152
  - `plugins?`: Better Auth 插件列表
138
153
  - `callbackURLBuilder?`: 自定义回调 URL 构建函数
139
154
  - `getSessionEndpoint?`: 获取 session 的端点路径(默认: `'/v1/auth/get-session'`)
155
+ - ~~`defaultRedirectAfterLogin?`~~: (已废弃) 建议在 SignInPage 组件中通过 `redirectUrl` prop 传入
156
+ - ~~`signInPath?`~~: (已废弃) 建议在 ProtectedRoute 组件中通过 `onUnauthorized` 回调处理导航
140
157
 
141
158
  **返回:** `AuthInstance`
142
159
 
@@ -190,9 +207,9 @@ Better Auth 认证状态同步组件。
190
207
 
191
208
  - `auth`: AuthInstance
192
209
  - `children`: React.ReactNode
193
- - `signInPath?`: 登录页面路径(默认: `'/sign-in'`)
194
- - `loadingComponent?`: 加载中组件
195
- - `loadingMessage?`: 加载中消息(默认: `'Checking authentication...'`)
210
+ - `onUnauthorized`: () => void - 当用户未认证时的回调函数(用于导航到登录页)
211
+ - `loadingComponent?`: React.ComponentType<{ message?: string }> - 自定义加载组件
212
+ - `loadingMessage?`: string - 加载中消息(默认: `'Checking authentication...'`)
196
213
 
197
214
  ### `SignInPage`
198
215
 
@@ -201,15 +218,16 @@ Better Auth 认证状态同步组件。
201
218
  **Props:**
202
219
 
203
220
  - `auth`: AuthInstance
204
- - `className?`: 自定义样式类名
205
- - `logo?`: Logo 组件
206
- - `title?`: 标题
207
- - `description?`: 描述
208
- - `provider?`: OAuth 提供商(默认: `'github'`)
209
- - `redirectAfterLogin?`: 登录后跳转地址(默认: `'/explore'`)
210
- - `signInButtonText?`: 登录按钮文本(默认: `'Sign in with GitHub'`)
211
- - `signingInButtonText?`: 登录中按钮文本(默认: `'Redirecting to GitHub...'`)
212
- - `signInButtonIcon?`: 登录按钮图标
221
+ - `className?`: string - 自定义样式类名
222
+ - `title?`: string - 标题
223
+ - `description?`: string - 描述
224
+ - `provider?`: string - OAuth 提供商(默认: `'github'`)
225
+ - `redirectUrl?`: string - OAuth 回调重定向地址(默认: `'/explore'`)
226
+ - `onAuthSuccess?`: () => void - 认证成功后的回调函数(用于导航)
227
+ - `githubButton?`: (isSigningIn: boolean) => React.ReactNode - 自定义 GitHub 登录按钮渲染函数
228
+ - `beforeElement?`: React.ReactNode - 在登录表单之前渲染的元素
229
+ - `afterElement?`: React.ReactNode - 在登录表单之后渲染的元素
230
+ - `footerText?`: React.ReactNode - 页脚文本
213
231
 
214
232
  ## 工具函数
215
233
 
@@ -440,13 +458,17 @@ try {
440
458
 
441
459
  ### 5. 退出登录
442
460
 
443
- 退出登录时使用 `signOut` 方法:
461
+ 退出登录时使用 `signOut` 方法,可以选择性地传入重定向地址:
444
462
 
445
463
  ```typescript
446
464
  async function handleSignOut() {
447
465
  try {
448
- await auth.authActions.signOut()
449
- // 用户将被重定向到登录页面
466
+ // 传入重定向地址,登出后会自动跳转
467
+ await auth.authActions.signOut("/sign-in")
468
+
469
+ // 或者不传入地址,由调用方手动处理后续导航
470
+ // await auth.authActions.signOut()
471
+ // navigate("/sign-in")
450
472
  } catch (error) {
451
473
  console.error("Sign out failed:", error)
452
474
  }
@@ -7,7 +7,7 @@ interface ProtectedRouteProps {
7
7
  message?: string;
8
8
  }>;
9
9
  loadingMessage?: string;
10
- signInPath?: string;
10
+ onUnauthorized: () => void;
11
11
  }
12
12
  /**
13
13
  * 路由保护组件
@@ -1 +1 @@
1
- {"version":3,"file":"protected-route.d.ts","sourceRoot":"","sources":["../../src/components/protected-route.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,UAAU,mBAAmB;IAC3B,IAAI,EAAE,YAAY,CAAA;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8BxD,CAAA;AAED,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"protected-route.d.ts","sourceRoot":"","sources":["../../src/components/protected-route.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoB,MAAM,OAAO,CAAA;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,UAAU,mBAAmB;IAC3B,IAAI,EAAE,YAAY,CAAA;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,gBAAgB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgCxD,CAAA;AAED,eAAe,cAAc,CAAA"}
@@ -1,15 +1,21 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { observer } from "@legendapp/state/react";
3
- import { Navigate } from "react-router";
3
+ import { useEffect } from "react";
4
4
  /**
5
5
  * 路由保护组件
6
6
  * 等待认证初始化完成,根据认证状态进行路由保护
7
7
  */
8
- export const ProtectedRoute = observer(({ children, auth, signInPath = "/sign-in", loadingComponent, loadingMessage }) => {
8
+ export const ProtectedRoute = observer(({ children, auth, loadingComponent, loadingMessage, onUnauthorized }) => {
9
9
  const { authStore, authComputed } = auth;
10
10
  // 检查各种状态
11
11
  const isInitializing = authComputed.isInitializing.get();
12
12
  const isAuthenticated = authStore.isAuthenticated.get();
13
+ // 当未认证时调用回调
14
+ useEffect(() => {
15
+ if (!isInitializing && !isAuthenticated) {
16
+ onUnauthorized();
17
+ }
18
+ }, [isInitializing, isAuthenticated, onUnauthorized]);
13
19
  // 检查初始化状态
14
20
  if (isInitializing) {
15
21
  if (loadingComponent) {
@@ -20,7 +26,7 @@ export const ProtectedRoute = observer(({ children, auth, signInPath = "/sign-in
20
26
  }
21
27
  // 检查认证状态
22
28
  if (!isAuthenticated) {
23
- return (_jsx(Navigate, { to: signInPath, replace: true }));
29
+ return null;
24
30
  }
25
31
  // 所有检查通过,渲染子组件
26
32
  return _jsx(_Fragment, { children: children });
@@ -8,13 +8,14 @@ interface SignInPageProps {
8
8
  description?: string;
9
9
  footerText?: React.ReactNode;
10
10
  githubButton?: (isSigningIn: boolean) => React.ReactNode;
11
+ onAuthSuccess?: () => void;
11
12
  provider?: string;
12
- redirectAfterLogin?: string;
13
+ redirectUrl?: string;
13
14
  title?: string;
14
15
  }
15
16
  /**
16
17
  * 登录页面组件
17
18
  */
18
- export declare function SignInPage({ afterElement, auth, beforeElement, redirectAfterLogin, provider, title, description, githubButton, className, footerText, }: SignInPageProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function SignInPage({ afterElement, auth, beforeElement, onAuthSuccess, redirectUrl, provider, title, description, githubButton, className, footerText, }: SignInPageProps): import("react/jsx-runtime").JSX.Element;
19
20
  export {};
20
21
  //# sourceMappingURL=sign-in-page.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sign-in-page.d.ts","sourceRoot":"","sources":["../../src/components/sign-in-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAElD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,UAAU,eAAe;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,IAAI,EACJ,aAAa,EACb,kBAA+B,EAC/B,QAAmB,EACnB,KAAK,EACL,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,GACX,EAAE,eAAe,2CAgDjB"}
1
+ {"version":3,"file":"sign-in-page.d.ts","sourceRoot":"","sources":["../../src/components/sign-in-page.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C,UAAU,eAAe;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,IAAI,EAAE,YAAY,CAAA;IAClB,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC5B,YAAY,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAA;IACxD,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EACzB,YAAY,EACZ,IAAI,EACJ,aAAa,EACb,aAAa,EACb,WAA0B,EAC1B,QAAmB,EACnB,KAAK,EACL,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,GACX,EAAE,eAAe,2CA+CjB"}
@@ -2,25 +2,23 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Slot } from "@choiceform/design-system";
3
3
  import { use$ } from "@legendapp/state/react";
4
4
  import { useEffect, useState } from "react";
5
- import { useNavigate } from "react-router";
6
5
  /**
7
6
  * 登录页面组件
8
7
  */
9
- export function SignInPage({ afterElement, auth, beforeElement, redirectAfterLogin = "/explore", provider = "github", title, description, githubButton, className, footerText, }) {
10
- const navigate = useNavigate();
8
+ export function SignInPage({ afterElement, auth, beforeElement, onAuthSuccess, redirectUrl = "/community", provider = "github", title, description, githubButton, className, footerText, }) {
11
9
  const { authStore, authActions } = auth;
12
10
  const { isAuthenticated, error } = use$(authStore);
13
11
  const [isSigningIn, setIsSigningIn] = useState(false);
14
12
  useEffect(() => {
15
- if (isAuthenticated) {
16
- navigate(redirectAfterLogin);
13
+ if (isAuthenticated && onAuthSuccess) {
14
+ onAuthSuccess();
17
15
  }
18
- }, [isAuthenticated, navigate, redirectAfterLogin]);
16
+ }, [isAuthenticated, onAuthSuccess]);
19
17
  const handleSignIn = async () => {
20
18
  // 设置本地 loading 状态
21
19
  setIsSigningIn(true);
22
20
  try {
23
- await authActions.signIn(provider, `${window.location.origin}${redirectAfterLogin}`);
21
+ await authActions.signIn(provider, `${window.location.origin}${redirectUrl}`);
24
22
  // OAuth 会重定向,所以这里的代码可能不会执行
25
23
  // loading 状态会在页面刷新后重置
26
24
  }
package/dist/config.d.ts CHANGED
@@ -16,8 +16,10 @@ export interface AuthConfig {
16
16
  */
17
17
  callbackURLBuilder?: (redirectTo: string, baseURL: string) => string;
18
18
  /**
19
- * OAuth 重定向后的默认跳转地址
20
- * @default '/explore'
19
+ * OAuth 重定向后的默认跳转地址(可选)
20
+ * 推荐在组件层面通过 props 传入,而不是在配置中设置
21
+ * @default undefined
22
+ * @deprecated 建议在 SignInPage 组件中通过 redirectUrl prop 传入
21
23
  */
22
24
  defaultRedirectAfterLogin?: string;
23
25
  /**
@@ -30,10 +32,18 @@ export interface AuthConfig {
30
32
  */
31
33
  plugins?: BetterAuthPlugin[];
32
34
  /**
33
- * 登录页面的路由路径
34
- * @default '/sign-in'
35
+ * 登录页面的路由路径(可选)
36
+ * 推荐在组件层面通过回调传入,而不是在配置中设置
37
+ * @default undefined
38
+ * @deprecated 建议在 ProtectedRoute 组件中通过 onUnauthorized 回调处理导航
35
39
  */
36
40
  signInPath?: string;
41
+ /**
42
+ * 跳过错误时的 token 清除(开发环境用)
43
+ * 启用后,网络错误、解析错误等不会清除 token,避免开发时频繁登出
44
+ * @default false
45
+ */
46
+ skipTokenCleanupOnError?: boolean;
37
47
  /**
38
48
  * Token 存储的 localStorage key
39
49
  * @default 'auth-token'
@@ -43,8 +53,11 @@ export interface AuthConfig {
43
53
  /**
44
54
  * 默认配置
45
55
  */
46
- export declare const defaultAuthConfig: Required<Omit<AuthConfig, "plugins" | "callbackURLBuilder">> & {
56
+ export declare const defaultAuthConfig: Required<Omit<AuthConfig, "plugins" | "callbackURLBuilder" | "defaultRedirectAfterLogin" | "signInPath" | "skipTokenCleanupOnError">> & {
47
57
  callbackURLBuilder: (redirectTo: string, baseURL: string) => string;
58
+ defaultRedirectAfterLogin: undefined;
48
59
  plugins: BetterAuthPlugin[];
60
+ signInPath: undefined;
61
+ skipTokenCleanupOnError: false;
49
62
  };
50
63
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,CACvC,cAAc,4BAA4B,EAAE,WAAW,CACxD,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IAEpE;;;OAGG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAElC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;OAEG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAE5B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,oBAAoB,CAAC,CAAC,GAAG;IAC7F,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACnE,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAW5B,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,CACvC,cAAc,4BAA4B,EAAE,WAAW,CACxD,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IAEpE;;;;;OAKG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAElC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B;;OAEG;IACH,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAE5B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAA;IAEjC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CACtC,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,oBAAoB,GAAG,2BAA2B,GAAG,YAAY,GAAG,yBAAyB,CAAC,CAC5H,GAAG;IACF,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;IACnE,yBAAyB,EAAE,SAAS,CAAA;IACpC,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,UAAU,EAAE,SAAS,CAAA;IACrB,uBAAuB,EAAE,KAAK,CAAA;CAY/B,CAAA"}
package/dist/config.js CHANGED
@@ -6,9 +6,10 @@ export const defaultAuthConfig = {
6
6
  callbackURLBuilder: (redirectTo, baseURL) => {
7
7
  return `${baseURL}/v1/auth/redirect?to=${encodeURIComponent(redirectTo)}`;
8
8
  },
9
- defaultRedirectAfterLogin: "/explore",
9
+ defaultRedirectAfterLogin: undefined,
10
10
  getSessionEndpoint: "/v1/auth/get-session",
11
11
  plugins: [],
12
- signInPath: "/sign-in",
12
+ signInPath: undefined,
13
+ skipTokenCleanupOnError: false,
13
14
  tokenStorageKey: "auth-token",
14
15
  };
@@ -0,0 +1,7 @@
1
+ import type { AuthInstance } from "../core";
2
+ /**
3
+ * 同步版本的认证初始化
4
+ * 可以在应用渲染前调用(非 React hook)
5
+ */
6
+ export declare function initAuthSync(auth: AuthInstance): Promise<void>;
7
+ //# sourceMappingURL=init-auth-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-auth-sync.d.ts","sourceRoot":"","sources":["../../src/core/init-auth-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAE3C;;;GAGG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BpE"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 同步版本的认证初始化
3
+ * 可以在应用渲染前调用(非 React hook)
4
+ */
5
+ export async function initAuthSync(auth) {
6
+ const { authActions, tokenStorage } = auth;
7
+ // 检查 URL 中的 token
8
+ const urlParams = new URLSearchParams(window.location.search);
9
+ let tokenFromUrl = urlParams.get("token");
10
+ if (tokenFromUrl) {
11
+ if (decodeURIComponent(tokenFromUrl) === tokenFromUrl) {
12
+ tokenFromUrl = encodeURIComponent(tokenFromUrl);
13
+ }
14
+ // 立即清理 URL 中的 token 参数(避免暴露)
15
+ urlParams.delete("token");
16
+ const newUrl = urlParams.toString()
17
+ ? `${window.location.pathname}?${urlParams.toString()}`
18
+ : window.location.pathname;
19
+ window.history.replaceState({}, "", newUrl);
20
+ // 使用 token 获取 session
21
+ await authActions.fetchSessionWithToken(tokenFromUrl);
22
+ }
23
+ else {
24
+ // 检查 localStorage 中是否有存储的 token
25
+ const storedToken = tokenStorage.get();
26
+ if (storedToken) {
27
+ await authActions.fetchSessionWithToken(storedToken);
28
+ }
29
+ else {
30
+ // 没有 token,标记为已加载
31
+ await authActions.initialize(null, true);
32
+ }
33
+ }
34
+ }