@choiceform/shared-auth 0.1.17 → 0.1.18

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.
Files changed (105) hide show
  1. package/README.md +286 -134
  2. package/dist/__tests__/auth-utils.test.d.ts +5 -0
  3. package/dist/__tests__/auth-utils.test.d.ts.map +1 -0
  4. package/dist/__tests__/auth-utils.test.js +96 -0
  5. package/dist/__tests__/store.test.d.ts +5 -0
  6. package/dist/__tests__/store.test.d.ts.map +1 -0
  7. package/dist/__tests__/store.test.js +210 -0
  8. package/dist/__tests__/user-mapper.test.d.ts +5 -0
  9. package/dist/__tests__/user-mapper.test.d.ts.map +1 -0
  10. package/dist/__tests__/user-mapper.test.js +76 -0
  11. package/dist/api/auth-api.d.ts +93 -9
  12. package/dist/api/auth-api.d.ts.map +1 -1
  13. package/dist/api/auth-api.js +219 -80
  14. package/dist/api/client.d.ts +10 -0
  15. package/dist/api/client.d.ts.map +1 -1
  16. package/dist/api/client.js +10 -0
  17. package/dist/api/organization-api.d.ts +2 -7
  18. package/dist/api/organization-api.d.ts.map +1 -1
  19. package/dist/api/organization-api.js +2 -17
  20. package/dist/api/team-api.d.ts +1 -5
  21. package/dist/api/team-api.d.ts.map +1 -1
  22. package/dist/api/team-api.js +5 -11
  23. package/dist/components/auth-sync.d.ts +27 -0
  24. package/dist/components/auth-sync.d.ts.map +1 -0
  25. package/dist/components/auth-sync.js +117 -0
  26. package/dist/components/protected-route.d.ts +18 -0
  27. package/dist/components/protected-route.d.ts.map +1 -0
  28. package/dist/components/protected-route.js +34 -0
  29. package/dist/components/sign-in-page.d.ts +21 -0
  30. package/dist/components/sign-in-page.d.ts.map +1 -0
  31. package/dist/components/sign-in-page.js +31 -0
  32. package/dist/config.js +1 -1
  33. package/dist/core.d.ts +148 -71
  34. package/dist/core.d.ts.map +1 -1
  35. package/dist/core.js +109 -28
  36. package/dist/hooks/index.d.ts +8 -0
  37. package/dist/hooks/index.d.ts.map +1 -0
  38. package/dist/hooks/index.js +7 -0
  39. package/dist/hooks/use-auth-init.d.ts +4 -0
  40. package/dist/hooks/use-auth-init.d.ts.map +1 -1
  41. package/dist/hooks/use-auth-init.js +16 -21
  42. package/dist/hooks/use-auth-sync.d.ts +60 -0
  43. package/dist/hooks/use-auth-sync.d.ts.map +1 -0
  44. package/dist/hooks/use-auth-sync.js +116 -0
  45. package/dist/hooks/use-email-verification.d.ts +85 -0
  46. package/dist/hooks/use-email-verification.d.ts.map +1 -0
  47. package/dist/hooks/use-email-verification.js +145 -0
  48. package/dist/hooks/use-protected-route.d.ts +67 -0
  49. package/dist/hooks/use-protected-route.d.ts.map +1 -0
  50. package/dist/hooks/use-protected-route.js +102 -0
  51. package/dist/index.d.ts +12 -6
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +43 -13
  54. package/dist/init.d.ts +127 -70
  55. package/dist/init.d.ts.map +1 -1
  56. package/dist/lib/auth-client.d.ts.map +1 -1
  57. package/dist/lib/auth-client.js +75 -2
  58. package/dist/services/auth-service.d.ts +101 -0
  59. package/dist/services/auth-service.d.ts.map +1 -0
  60. package/dist/services/auth-service.js +356 -0
  61. package/dist/services/callback-service.d.ts +33 -0
  62. package/dist/services/callback-service.d.ts.map +1 -0
  63. package/dist/services/callback-service.js +473 -0
  64. package/dist/services/companion-team.d.ts.map +1 -1
  65. package/dist/services/companion-team.js +41 -39
  66. package/dist/services/index.d.ts +2 -0
  67. package/dist/services/index.d.ts.map +1 -1
  68. package/dist/services/index.js +2 -0
  69. package/dist/store/actions.d.ts +54 -51
  70. package/dist/store/actions.d.ts.map +1 -1
  71. package/dist/store/actions.js +111 -243
  72. package/dist/store/computed.d.ts +72 -1
  73. package/dist/store/computed.d.ts.map +1 -1
  74. package/dist/store/computed.js +90 -3
  75. package/dist/store/index.d.ts +3 -3
  76. package/dist/store/index.d.ts.map +1 -1
  77. package/dist/store/index.js +2 -2
  78. package/dist/store/state.d.ts +10 -0
  79. package/dist/store/state.d.ts.map +1 -1
  80. package/dist/store/state.js +11 -1
  81. package/dist/store/utils.d.ts +3 -34
  82. package/dist/store/utils.d.ts.map +1 -1
  83. package/dist/store/utils.js +2 -22
  84. package/dist/types/auth.d.ts +106 -0
  85. package/dist/types/auth.d.ts.map +1 -1
  86. package/dist/types/callback.d.ts +35 -0
  87. package/dist/types/callback.d.ts.map +1 -0
  88. package/dist/types/callback.js +1 -0
  89. package/dist/types/index.d.ts +4 -3
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/dist/types/organization.d.ts +19 -3
  92. package/dist/types/organization.d.ts.map +1 -1
  93. package/dist/types/team.d.ts +6 -2
  94. package/dist/types/team.d.ts.map +1 -1
  95. package/dist/types/user.d.ts +7 -3
  96. package/dist/types/user.d.ts.map +1 -1
  97. package/dist/utils/auth-utils.d.ts +60 -0
  98. package/dist/utils/auth-utils.d.ts.map +1 -0
  99. package/dist/utils/auth-utils.js +146 -0
  100. package/dist/utils/index.d.ts +1 -0
  101. package/dist/utils/index.d.ts.map +1 -1
  102. package/dist/utils/index.js +1 -0
  103. package/dist/utils/user-mapper.d.ts.map +1 -1
  104. package/dist/utils/user-mapper.js +2 -1
  105. package/package.json +10 -2
@@ -1,85 +1,88 @@
1
1
  /**
2
- * 认证 Actions
2
+ * 认证状态 Actions
3
+ *
4
+ * 只负责状态管理,不包含业务逻辑
5
+ * 业务逻辑在 services/auth-service.ts 中
3
6
  */
4
7
  import type { Observable } from "@legendapp/state";
5
- import type { AuthClientMethods, AuthConfig, AuthState, SessionUser } from "../types";
8
+ import type { AuthState, SessionUser } from "../types";
6
9
  import type { TokenStorage } from "../api";
7
10
  /**
8
- * 创建认证 Actions
11
+ * 创建状态管理 Actions
12
+ *
13
+ * 这些是纯粹的状态操作,不涉及 API 调用或业务逻辑
9
14
  */
10
- export declare function createAuthActions(authStore: Observable<AuthState>, tokenStorage: TokenStorage, config: AuthConfig, authClient: AuthClientMethods): {
15
+ export declare function createStoreActions(authStore: Observable<AuthState>, tokenStorage: TokenStorage): {
11
16
  /**
12
- * 初始化认证状态
17
+ * 获取当前用户
13
18
  */
14
- initialize(user: SessionUser | null, isLoaded: boolean): Promise<void>;
19
+ getUser(): SessionUser | null;
15
20
  /**
16
- * 使用 Bearer Token 获取 session
21
+ * 获取当前用户 ID
17
22
  */
18
- fetchSessionWithToken(token: string): Promise<void>;
23
+ getUserId(): string | null;
19
24
  /**
20
- * 处理未授权
25
+ * 检查是否已认证
21
26
  */
22
- handleUnauthorized(): void;
27
+ isAuthenticated(): boolean;
28
+ /**
29
+ * 检查是否正在加载
30
+ */
31
+ isLoading(): boolean;
32
+ /**
33
+ * 检查是否已加载完成
34
+ */
35
+ isLoaded(): boolean;
36
+ /**
37
+ * 设置用户
38
+ */
39
+ setUser(user: SessionUser | null): void;
40
+ /**
41
+ * 更新用户(合并)
42
+ */
43
+ updateUser(updates: Partial<SessionUser>): void;
23
44
  /**
24
45
  * 设置加载状态
25
46
  */
26
47
  setLoading(loading: boolean): void;
27
48
  /**
28
- * 设置错误信息
49
+ * 设置已加载状态
29
50
  */
30
- setError(error: string | null): void;
51
+ setLoaded(loaded: boolean): void;
31
52
  /**
32
- * OAuth 登录
33
- *
34
- * 直接调用 better-auth 的 signIn.social,传入完整的回调 URL
35
- *
36
- * @param provider - OAuth 提供商(如 github)
37
- * @param callbackURL - 登录成功后的完整回调 URL
38
- * @param newUserCallbackURL - 新用户的回调 URL(可选)
39
- * @param errorCallbackURL - 登录失败后的完整回调 URL(可选)
53
+ * 设置错误
40
54
  */
41
- signIn(provider: string, callbackURL: string, newUserCallbackURL?: string, errorCallbackURL?: string): Promise<void>;
55
+ setError(error: string | null): void;
42
56
  /**
43
- * Magic Link 登录
44
- *
45
- * 发送 Magic Link 到用户邮箱
46
- *
47
- * @param email - 用户邮箱
48
- * @param callbackURL - 登录成功后的完整回调 URL
49
- * @param name - 用户名称(可选,用于新用户)
50
- * @param newUserCallbackURL - 新用户的回调 URL(可选)
51
- * @returns 是否发送成功
57
+ * 设置认证成功状态
52
58
  */
53
- signInWithMagicLink(email: string, callbackURL: string, name?: string, newUserCallbackURL?: string): Promise<boolean>;
59
+ setAuthenticated(user: SessionUser): void;
54
60
  /**
55
- * Email/Password 登录
56
- *
57
- * @param email - 邮箱
58
- * @param password - 密码
59
- * @returns 是否登录成功
61
+ * 清除认证状态
60
62
  */
61
- signInWithEmail(email: string, password: string): Promise<boolean>;
63
+ clearAuth(): void;
62
64
  /**
63
- * Email/Password 注册
64
- *
65
- * @param email - 邮箱
66
- * @param password - 密码
67
- * @param name - 用户名
68
- * @returns 是否注册成功
65
+ * 处理未授权
69
66
  */
70
- signUpWithEmail(email: string, password: string, name: string): Promise<boolean>;
67
+ handleUnauthorized(): void;
71
68
  /**
72
- * 登出
69
+ * 更新活跃组织 ID
73
70
  */
74
- signOut(redirectTo?: string): Promise<void>;
71
+ setActiveOrganizationId(organizationId: string | null | undefined): void;
75
72
  /**
76
- * 更新用户信息
73
+ * 更新活跃团队 ID
77
74
  */
78
- updateUser(user: SessionUser | null): void;
75
+ setActiveTeamId(teamId: string | null | undefined): void;
79
76
  /**
80
- * 获取当前用户
77
+ * 初始化认证状态
81
78
  */
82
- getUser(): SessionUser | null;
79
+ initialize(user: SessionUser | null, isLoaded: boolean): void;
83
80
  };
84
- export type AuthActions = ReturnType<typeof createAuthActions>;
81
+ export type StoreActions = ReturnType<typeof createStoreActions>;
82
+ /**
83
+ * @deprecated 使用 createStoreActions 代替
84
+ * 保留此函数以保持向后兼容性
85
+ */
86
+ export { createStoreActions as createAuthActions };
87
+ export type { StoreActions as AuthActions };
85
88
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/store/actions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAG1C;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAChC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,iBAAiB;IAS3B;;OAEG;qBACoB,WAAW,GAAG,IAAI,YAAY,OAAO;IAe5D;;OAEG;iCACgC,MAAM;IAgDzC;;OAEG;;IAcH;;OAEG;wBACiB,OAAO;IAI3B;;OAEG;oBACa,MAAM,GAAG,IAAI;IAI7B;;;;;;;;;OASG;qBACoB,MAAM,eAAe,MAAM,uBAAuB,MAAM,qBAAqB,MAAM;IAsB1G;;;;;;;;;;OAUG;+BAEM,MAAM,eACA,MAAM,SACZ,MAAM,uBACQ,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC;IA+BnB;;;;;;OAMG;2BAC0B,MAAM,YAAY,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuCxE;;;;;;;OAOG;2BAEM,MAAM,YACH,MAAM,QACV,MAAM,GACX,OAAO,CAAC,OAAO,CAAC;IAuCnB;;OAEG;yBACwB,MAAM;IA6BjC;;OAEG;qBACc,WAAW,GAAG,IAAI;IAUnC;;OAEG;eACQ,WAAW,GAAG,IAAI;EAIhC;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/store/actions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAE1C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,EAChC,YAAY,EAAE,YAAY;IAOxB;;OAEG;eACQ,WAAW,GAAG,IAAI;IAI7B;;OAEG;iBACU,MAAM,GAAG,IAAI;IAI1B;;OAEG;uBACgB,OAAO;IAI1B;;OAEG;iBACU,OAAO;IAIpB;;OAEG;gBACS,OAAO;IAQnB;;OAEG;kBACW,WAAW,GAAG,IAAI;IAKhC;;OAEG;wBACiB,OAAO,CAAC,WAAW,CAAC;IAOxC;;OAEG;wBACiB,OAAO;IAI3B;;OAEG;sBACe,OAAO;IAOzB;;OAEG;oBACa,MAAM,GAAG,IAAI;IAI7B;;OAEG;2BACoB,WAAW;IAQlC;;OAEG;;IASH;;OAEG;;IASH;;OAEG;4CACqC,MAAM,GAAG,IAAI,GAAG,SAAS;IAUjE;;OAEG;4BACqB,MAAM,GAAG,IAAI,GAAG,SAAS;IAcjD;;OAEG;qBACc,WAAW,GAAG,IAAI,YAAY,OAAO;EAWzD;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAMhE;;;GAGG;AACH,OAAO,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,CAAA;AAClD,YAAY,EAAE,YAAY,IAAI,WAAW,EAAE,CAAA"}
@@ -1,91 +1,67 @@
1
1
  /**
2
- * 认证 Actions
2
+ * 认证状态 Actions
3
+ *
4
+ * 只负责状态管理,不包含业务逻辑
5
+ * 业务逻辑在 services/auth-service.ts 中
3
6
  */
4
- import { extractSessionUser } from "../utils";
5
7
  /**
6
- * 创建认证 Actions
8
+ * 创建状态管理 Actions
9
+ *
10
+ * 这些是纯粹的状态操作,不涉及 API 调用或业务逻辑
7
11
  */
8
- export function createAuthActions(authStore, tokenStorage, config, authClient) {
9
- const { baseURL, getSessionEndpoint = "/v1/auth/get-session", skipTokenCleanupOnError = false, } = config;
12
+ export function createStoreActions(authStore, tokenStorage) {
10
13
  return {
14
+ // ============================================================
15
+ // 状态读取
16
+ // ============================================================
11
17
  /**
12
- * 初始化认证状态
18
+ * 获取当前用户
13
19
  */
14
- async initialize(user, isLoaded) {
15
- const storedToken = tokenStorage.get();
16
- if (!user && storedToken) {
17
- await this.fetchSessionWithToken(storedToken);
18
- }
19
- else if (user) {
20
- authStore.user.set(user);
21
- authStore.isAuthenticated.set(true);
22
- }
23
- else {
24
- authStore.user.set(null);
25
- authStore.isAuthenticated.set(false);
26
- }
27
- authStore.isLoaded.set(isLoaded);
28
- authStore.loading.set(!isLoaded);
20
+ getUser() {
21
+ return authStore.user.get();
29
22
  },
30
23
  /**
31
- * 使用 Bearer Token 获取 session
24
+ * 获取当前用户 ID
32
25
  */
33
- async fetchSessionWithToken(token) {
34
- try {
35
- if (!token) {
36
- throw new Error("Token is required");
37
- }
38
- tokenStorage.save(token);
39
- const endpoint = `${baseURL}${getSessionEndpoint}`;
40
- const response = await fetch(endpoint, {
41
- method: "GET",
42
- headers: {
43
- Authorization: `Bearer ${token}`,
44
- "Content-Type": "application/json",
45
- },
46
- });
47
- if (!response.ok) {
48
- throw new Error(`Failed to fetch session: ${response.status}`);
49
- }
50
- const responseText = await response.text();
51
- let sessionData = null;
52
- try {
53
- if (responseText && responseText !== "null" && responseText !== "") {
54
- sessionData = JSON.parse(responseText);
55
- }
56
- }
57
- catch {
58
- this.handleUnauthorized();
59
- return;
60
- }
61
- const userData = extractSessionUser(sessionData);
62
- if (userData) {
63
- authStore.user.set(userData);
64
- authStore.isAuthenticated.set(true);
65
- authStore.isLoaded.set(true);
66
- authStore.loading.set(false);
67
- }
68
- else {
69
- this.handleUnauthorized();
70
- }
71
- }
72
- catch {
73
- this.handleUnauthorized();
74
- }
26
+ getUserId() {
27
+ return authStore.user.get()?.id ?? null;
75
28
  },
76
29
  /**
77
- * 处理未授权
30
+ * 检查是否已认证
78
31
  */
79
- handleUnauthorized() {
80
- authStore.user.set(null);
81
- authStore.isAuthenticated.set(false);
82
- authStore.isLoaded.set(true);
83
- authStore.loading.set(false);
84
- if (skipTokenCleanupOnError) {
85
- console.warn("[Auth] Token cleanup skipped (skipTokenCleanupOnError is enabled)");
86
- return;
32
+ isAuthenticated() {
33
+ return authStore.isAuthenticated.get();
34
+ },
35
+ /**
36
+ * 检查是否正在加载
37
+ */
38
+ isLoading() {
39
+ return authStore.loading.get();
40
+ },
41
+ /**
42
+ * 检查是否已加载完成
43
+ */
44
+ isLoaded() {
45
+ return authStore.isLoaded.get();
46
+ },
47
+ // ============================================================
48
+ // 状态更新
49
+ // ============================================================
50
+ /**
51
+ * 设置用户
52
+ */
53
+ setUser(user) {
54
+ authStore.user.set(user);
55
+ authStore.isAuthenticated.set(user !== null);
56
+ },
57
+ /**
58
+ * 更新用户(合并)
59
+ */
60
+ updateUser(updates) {
61
+ const currentUser = authStore.user.get();
62
+ if (currentUser) {
63
+ authStore.user.set({ ...currentUser, ...updates });
87
64
  }
88
- tokenStorage.clear();
89
65
  },
90
66
  /**
91
67
  * 设置加载状态
@@ -94,205 +70,97 @@ export function createAuthActions(authStore, tokenStorage, config, authClient) {
94
70
  authStore.loading.set(loading);
95
71
  },
96
72
  /**
97
- * 设置错误信息
73
+ * 设置已加载状态
74
+ */
75
+ setLoaded(loaded) {
76
+ authStore.isLoaded.set(loaded);
77
+ if (loaded) {
78
+ authStore.loading.set(false);
79
+ }
80
+ },
81
+ /**
82
+ * 设置错误
98
83
  */
99
84
  setError(error) {
100
85
  authStore.error.set(error);
101
86
  },
102
87
  /**
103
- * OAuth 登录
104
- *
105
- * 直接调用 better-auth 的 signIn.social,传入完整的回调 URL
106
- *
107
- * @param provider - OAuth 提供商(如 github)
108
- * @param callbackURL - 登录成功后的完整回调 URL
109
- * @param newUserCallbackURL - 新用户的回调 URL(可选)
110
- * @param errorCallbackURL - 登录失败后的完整回调 URL(可选)
88
+ * 设置认证成功状态
111
89
  */
112
- async signIn(provider, callbackURL, newUserCallbackURL, errorCallbackURL) {
113
- if (authStore.loading.get()) {
114
- return;
115
- }
116
- try {
117
- authStore.loading.set(true);
118
- authStore.error.set(null);
119
- await authClient.signIn.social({
120
- provider,
121
- callbackURL,
122
- newUserCallbackURL,
123
- errorCallbackURL,
124
- });
125
- }
126
- catch (error) {
127
- const message = error instanceof Error ? error.message : "Sign in failed";
128
- authStore.error.set(message);
129
- authStore.loading.set(false);
130
- }
90
+ setAuthenticated(user) {
91
+ authStore.user.set(user);
92
+ authStore.isAuthenticated.set(true);
93
+ authStore.isLoaded.set(true);
94
+ authStore.loading.set(false);
95
+ authStore.error.set(null);
131
96
  },
132
97
  /**
133
- * Magic Link 登录
134
- *
135
- * 发送 Magic Link 到用户邮箱
136
- *
137
- * @param email - 用户邮箱
138
- * @param callbackURL - 登录成功后的完整回调 URL
139
- * @param name - 用户名称(可选,用于新用户)
140
- * @param newUserCallbackURL - 新用户的回调 URL(可选)
141
- * @returns 是否发送成功
98
+ * 清除认证状态
142
99
  */
143
- async signInWithMagicLink(email, callbackURL, name, newUserCallbackURL) {
144
- if (authStore.loading.get()) {
145
- return false;
146
- }
147
- if (!authClient.signIn.magicLink) {
148
- authStore.error.set("Magic link is not available. Please add magicLinkClient() plugin.");
149
- return false;
150
- }
151
- try {
152
- authStore.loading.set(true);
153
- authStore.error.set(null);
154
- await authClient.signIn.magicLink({
155
- email,
156
- name,
157
- callbackURL,
158
- newUserCallbackURL,
159
- });
160
- authStore.loading.set(false);
161
- return true;
162
- }
163
- catch (error) {
164
- const message = error instanceof Error ? error.message : "Failed to send magic link";
165
- authStore.error.set(message);
166
- authStore.loading.set(false);
167
- return false;
168
- }
100
+ clearAuth() {
101
+ authStore.user.set(null);
102
+ authStore.isAuthenticated.set(false);
103
+ authStore.isLoaded.set(true);
104
+ authStore.loading.set(false);
105
+ tokenStorage.clear();
169
106
  },
170
107
  /**
171
- * Email/Password 登录
172
- *
173
- * @param email - 邮箱
174
- * @param password - 密码
175
- * @returns 是否登录成功
108
+ * 处理未授权
176
109
  */
177
- async signInWithEmail(email, password) {
178
- if (authStore.loading.get()) {
179
- return false;
180
- }
181
- if (!authClient.signIn.email) {
182
- authStore.error.set("Email sign in is not available.");
183
- return false;
184
- }
185
- try {
186
- authStore.loading.set(true);
187
- authStore.error.set(null);
188
- await authClient.signIn.email({ email, password }, {
189
- onSuccess: (context) => {
190
- const token = context.response.headers.get("set-auth-token");
191
- if (token) {
192
- tokenStorage.save(token);
193
- }
194
- },
195
- onError: (context) => {
196
- authStore.error.set(context.error.message || "Login failed");
197
- },
198
- });
199
- authStore.loading.set(false);
200
- return true;
201
- }
202
- catch (error) {
203
- const message = error instanceof Error ? error.message : "Login failed";
204
- authStore.error.set(message);
205
- authStore.loading.set(false);
206
- return false;
207
- }
110
+ handleUnauthorized() {
111
+ this.clearAuth();
208
112
  },
113
+ // ============================================================
114
+ // Active 状态更新
115
+ // ============================================================
209
116
  /**
210
- * Email/Password 注册
211
- *
212
- * @param email - 邮箱
213
- * @param password - 密码
214
- * @param name - 用户名
215
- * @returns 是否注册成功
117
+ * 更新活跃组织 ID
216
118
  */
217
- async signUpWithEmail(email, password, name) {
218
- if (authStore.loading.get()) {
219
- return false;
220
- }
221
- if (!authClient.signUp?.email) {
222
- authStore.error.set("Email sign up is not available.");
223
- return false;
224
- }
225
- try {
226
- authStore.loading.set(true);
227
- authStore.error.set(null);
228
- await authClient.signUp.email({ email, password, name }, {
229
- onSuccess: (context) => {
230
- const token = context.response.headers.get("set-auth-token");
231
- if (token) {
232
- tokenStorage.save(token);
233
- }
234
- },
235
- onError: (context) => {
236
- authStore.error.set(context.error.message || "Sign up failed");
237
- },
119
+ setActiveOrganizationId(organizationId) {
120
+ const currentUser = authStore.user.get();
121
+ if (currentUser) {
122
+ authStore.user.set({
123
+ ...currentUser,
124
+ activeOrganizationId: organizationId ?? undefined,
238
125
  });
239
- authStore.loading.set(false);
240
- return true;
241
- }
242
- catch (error) {
243
- const message = error instanceof Error ? error.message : "Sign up failed";
244
- authStore.error.set(message);
245
- authStore.loading.set(false);
246
- return false;
247
126
  }
248
127
  },
249
128
  /**
250
- * 登出
129
+ * 更新活跃团队 ID
251
130
  */
252
- async signOut(redirectTo) {
253
- if (authStore.loading.get()) {
254
- return;
255
- }
256
- try {
257
- authStore.loading.set(true);
258
- authStore.error.set(null);
259
- await authClient.signOut();
260
- authStore.user.set(null);
261
- authStore.isAuthenticated.set(false);
262
- tokenStorage.clear();
263
- if (redirectTo) {
264
- window.location.href = redirectTo;
265
- }
266
- }
267
- catch (error) {
268
- const message = error instanceof Error ? error.message : "Sign out failed";
269
- authStore.error.set(message);
270
- authStore.user.set(null);
271
- authStore.isAuthenticated.set(false);
272
- tokenStorage.clear();
273
- }
274
- finally {
275
- authStore.loading.set(false);
131
+ setActiveTeamId(teamId) {
132
+ const currentUser = authStore.user.get();
133
+ if (currentUser) {
134
+ authStore.user.set({
135
+ ...currentUser,
136
+ activeTeamId: teamId ?? undefined,
137
+ });
276
138
  }
277
139
  },
140
+ // ============================================================
141
+ // 初始化
142
+ // ============================================================
278
143
  /**
279
- * 更新用户信息
144
+ * 初始化认证状态
280
145
  */
281
- updateUser(user) {
146
+ initialize(user, isLoaded) {
282
147
  if (user) {
283
- authStore.user.set(user);
284
- authStore.isAuthenticated.set(true);
148
+ this.setAuthenticated(user);
285
149
  }
286
150
  else {
287
151
  authStore.user.set(null);
288
152
  authStore.isAuthenticated.set(false);
289
153
  }
290
- },
291
- /**
292
- * 获取当前用户
293
- */
294
- getUser() {
295
- return authStore.user.get();
154
+ authStore.isLoaded.set(isLoaded);
155
+ authStore.loading.set(!isLoaded);
296
156
  },
297
157
  };
298
158
  }
159
+ // ============================================================
160
+ // 兼容性导出(保持向后兼容)
161
+ // ============================================================
162
+ /**
163
+ * @deprecated 使用 createStoreActions 代替
164
+ * 保留此函数以保持向后兼容性
165
+ */
166
+ export { createStoreActions as createAuthActions };
@@ -1,3 +1,9 @@
1
+ /**
2
+ * 认证 Computed(派生状态)
3
+ *
4
+ * 基于 authStore 派生的响应式状态
5
+ * 这些都是只读的响应式值,会自动跟踪依赖并更新
6
+ */
1
7
  import type { Observable } from "@legendapp/state";
2
8
  import type { AuthState } from "../types";
3
9
  /**
@@ -5,8 +11,73 @@ import type { AuthState } from "../types";
5
11
  */
6
12
  export declare function createAuthComputed(authStore: Observable<AuthState>): {
7
13
  /**
8
- * 是否正在初始化
14
+ * 是否正在初始化(未加载完成)
9
15
  */
10
16
  isInitializing: import("@legendapp/state").ObservableBoolean;
17
+ /**
18
+ * 是否准备就绪(已加载且已认证)
19
+ */
20
+ isReady: import("@legendapp/state").ObservableBoolean;
21
+ /**
22
+ * 是否未认证(已加载但未认证)
23
+ */
24
+ isUnauthenticated: import("@legendapp/state").ObservableBoolean;
25
+ /**
26
+ * 是否有错误
27
+ */
28
+ hasError: import("@legendapp/state").ObservableBoolean;
29
+ /**
30
+ * 当前用户 ID
31
+ */
32
+ userId: import("@legendapp/state").ObservablePrimitive<string | null>;
33
+ /**
34
+ * 当前用户邮箱
35
+ */
36
+ userEmail: import("@legendapp/state").ObservablePrimitive<string | null>;
37
+ /**
38
+ * 当前用户名称
39
+ */
40
+ userName: import("@legendapp/state").ObservablePrimitive<string | null>;
41
+ /**
42
+ * 当前用户头像
43
+ */
44
+ userImage: import("@legendapp/state").ObservablePrimitive<string | null>;
45
+ /**
46
+ * 邮箱是否已验证
47
+ */
48
+ emailVerified: import("@legendapp/state").ObservableBoolean;
49
+ /**
50
+ * 当前活跃组织 ID
51
+ */
52
+ activeOrganizationId: import("@legendapp/state").ObservablePrimitive<string | null>;
53
+ /**
54
+ * 当前活跃团队 ID
55
+ */
56
+ activeTeamId: import("@legendapp/state").ObservablePrimitive<string | null>;
57
+ /**
58
+ * 伴生组织 ID(用户自己的组织)
59
+ */
60
+ inherentOrganizationId: import("@legendapp/state").ObservablePrimitive<string | null>;
61
+ /**
62
+ * 伴生团队 ID(用户自己的团队)
63
+ */
64
+ inherentTeamId: import("@legendapp/state").ObservablePrimitive<string | null>;
65
+ /**
66
+ * 是否有活跃组织
67
+ */
68
+ hasActiveOrganization: import("@legendapp/state").ObservableBoolean;
69
+ /**
70
+ * 是否有活跃团队
71
+ */
72
+ hasActiveTeam: import("@legendapp/state").ObservableBoolean;
73
+ /**
74
+ * 是否在伴生组织中(当前活跃组织是否是伴生组织)
75
+ */
76
+ isInInherentOrganization: import("@legendapp/state").ObservableBoolean;
77
+ /**
78
+ * 是否在伴生团队中(当前活跃团队是否是伴生团队)
79
+ */
80
+ isInInherentTeam: import("@legendapp/state").ObservableBoolean;
11
81
  };
82
+ export type AuthComputed = ReturnType<typeof createAuthComputed>;
12
83
  //# sourceMappingURL=computed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/store/computed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC;IAE/D;;OAEG;;EAKN"}
1
+ {"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/store/computed.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC;IAM/D;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAOH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAOH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAOH;;OAEG;;EAON;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAA"}