@choiceform/shared-auth 0.1.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.
Files changed (44) hide show
  1. package/README.md +452 -0
  2. package/dist/components/auth-sync.d.ts +9 -0
  3. package/dist/components/auth-sync.d.ts.map +1 -0
  4. package/dist/components/auth-sync.js +60 -0
  5. package/dist/components/protected-route.d.ts +18 -0
  6. package/dist/components/protected-route.d.ts.map +1 -0
  7. package/dist/components/protected-route.js +28 -0
  8. package/dist/components/sign-in-page.d.ts +49 -0
  9. package/dist/components/sign-in-page.d.ts.map +1 -0
  10. package/dist/components/sign-in-page.js +33 -0
  11. package/dist/config.d.ts +50 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +14 -0
  14. package/dist/core.d.ts +2162 -0
  15. package/dist/core.d.ts.map +1 -0
  16. package/dist/core.js +37 -0
  17. package/dist/hooks/use-auth-init.d.ts +7 -0
  18. package/dist/hooks/use-auth-init.d.ts.map +1 -0
  19. package/dist/hooks/use-auth-init.js +41 -0
  20. package/dist/index.d.ts +22 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +24 -0
  23. package/dist/init.d.ts +2167 -0
  24. package/dist/init.d.ts.map +1 -0
  25. package/dist/init.js +17 -0
  26. package/dist/lib/auth-client.d.ts +2120 -0
  27. package/dist/lib/auth-client.d.ts.map +1 -0
  28. package/dist/lib/auth-client.js +11 -0
  29. package/dist/store/actions.d.ts +60 -0
  30. package/dist/store/actions.d.ts.map +1 -0
  31. package/dist/store/actions.js +234 -0
  32. package/dist/store/computed.d.ts +12 -0
  33. package/dist/store/computed.d.ts.map +1 -0
  34. package/dist/store/computed.js +14 -0
  35. package/dist/store/state.d.ts +16 -0
  36. package/dist/store/state.d.ts.map +1 -0
  37. package/dist/store/state.js +52 -0
  38. package/dist/store/utils.d.ts +103 -0
  39. package/dist/store/utils.d.ts.map +1 -0
  40. package/dist/store/utils.js +198 -0
  41. package/dist/types.d.ts +37 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +4 -0
  44. package/package.json +65 -0
@@ -0,0 +1,198 @@
1
+ /**
2
+ * 获取当前用户
3
+ */
4
+ export function getCurrentUser(authStore) {
5
+ return authStore.user.get();
6
+ }
7
+ /**
8
+ * 获取当前用户ID
9
+ */
10
+ export function getCurrentUserId(authStore) {
11
+ return authStore.user.get()?.id || null;
12
+ }
13
+ /**
14
+ * 安全获取当前用户ID
15
+ */
16
+ export function getCurrentUserIdSafe(authStore) {
17
+ return getCurrentUserId(authStore);
18
+ }
19
+ /**
20
+ * 检查是否已认证
21
+ */
22
+ export function isAuthenticated(authStore) {
23
+ return authStore.isAuthenticated.get();
24
+ }
25
+ /**
26
+ * 检查是否正在加载
27
+ */
28
+ export function isLoading(authStore) {
29
+ return authStore.loading.get();
30
+ }
31
+ /**
32
+ * 检查是否已加载
33
+ */
34
+ export function isLoaded(authStore) {
35
+ return authStore.isLoaded.get();
36
+ }
37
+ /**
38
+ * 等待认证完成
39
+ * 使用轮询方式检查认证状态(简单但有效)
40
+ *
41
+ * 注意:如果长时间未加载,Promise 不会自动 reject
42
+ * 建议在外层添加超时处理
43
+ */
44
+ export async function waitForAuth(authStore) {
45
+ return new Promise((resolve) => {
46
+ // 如果已经加载,立即 resolve
47
+ if (authStore.isLoaded.get()) {
48
+ resolve();
49
+ return;
50
+ }
51
+ const checkAuth = () => {
52
+ if (authStore.isLoaded.get()) {
53
+ resolve();
54
+ }
55
+ else {
56
+ setTimeout(checkAuth, 100);
57
+ }
58
+ };
59
+ checkAuth();
60
+ });
61
+ }
62
+ /**
63
+ * 获取认证令牌
64
+ */
65
+ export async function getAuthToken(authStore, tokenStorage, authActions, authClient) {
66
+ // 首先从存储中获取 token
67
+ const storedToken = tokenStorage.get();
68
+ if (storedToken) {
69
+ // 如果有 token 但没有用户信息,尝试获取 session
70
+ if (!authStore.user.get()) {
71
+ await authActions.fetchSessionWithToken(storedToken);
72
+ }
73
+ return storedToken;
74
+ }
75
+ // 如果没有存储的 token,尝试从 session 获取
76
+ const sessionData = await authClient.getSession();
77
+ const sessionToken = sessionData?.data?.session?.token || null;
78
+ if (sessionToken) {
79
+ tokenStorage.save(sessionToken);
80
+ }
81
+ return sessionToken;
82
+ }
83
+ /**
84
+ * 获取认证头
85
+ */
86
+ export async function getAuthHeaders(authStore, tokenStorage, authActions, authClient) {
87
+ const token = await getAuthToken(authStore, tokenStorage, authActions, authClient);
88
+ if (!token) {
89
+ return {};
90
+ }
91
+ return {
92
+ Authorization: `Bearer ${encodeURIComponent(token)}`,
93
+ };
94
+ }
95
+ /**
96
+ * 处理 401 响应
97
+ */
98
+ export function handle401Response(response, authActions) {
99
+ if (response.status === 401) {
100
+ authActions.handleUnauthorized();
101
+ }
102
+ return response;
103
+ }
104
+ /**
105
+ * API 客户端工具
106
+ */
107
+ export function createApiClient(authStore, tokenStorage, authActions, authClient) {
108
+ return {
109
+ async get(url, options) {
110
+ const headers = await getAuthHeaders(authStore, tokenStorage, authActions, authClient);
111
+ const response = await fetch(url, {
112
+ ...options,
113
+ method: "GET",
114
+ headers: {
115
+ ...headers,
116
+ ...options?.headers,
117
+ },
118
+ });
119
+ return handle401Response(response, authActions);
120
+ },
121
+ async post(url, body, options) {
122
+ const headers = await getAuthHeaders(authStore, tokenStorage, authActions, authClient);
123
+ const response = await fetch(url, {
124
+ ...options,
125
+ method: "POST",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ ...headers,
129
+ ...options?.headers,
130
+ },
131
+ body: body ? JSON.stringify(body) : undefined,
132
+ });
133
+ return handle401Response(response, authActions);
134
+ },
135
+ async put(url, body, options) {
136
+ const headers = await getAuthHeaders(authStore, tokenStorage, authActions, authClient);
137
+ const response = await fetch(url, {
138
+ ...options,
139
+ method: "PUT",
140
+ headers: {
141
+ "Content-Type": "application/json",
142
+ ...headers,
143
+ ...options?.headers,
144
+ },
145
+ body: body ? JSON.stringify(body) : undefined,
146
+ });
147
+ return handle401Response(response, authActions);
148
+ },
149
+ async delete(url, options) {
150
+ const headers = await getAuthHeaders(authStore, tokenStorage, authActions, authClient);
151
+ const response = await fetch(url, {
152
+ ...options,
153
+ method: "DELETE",
154
+ headers: {
155
+ ...headers,
156
+ ...options?.headers,
157
+ },
158
+ });
159
+ return handle401Response(response, authActions);
160
+ },
161
+ };
162
+ }
163
+ /**
164
+ * 用户管理器
165
+ */
166
+ export function createUserManager(authStore) {
167
+ return {
168
+ getUser() {
169
+ return getCurrentUser(authStore);
170
+ },
171
+ getUserId() {
172
+ return getCurrentUserId(authStore);
173
+ },
174
+ };
175
+ }
176
+ /**
177
+ * 从 AuthInstance 创建绑定好的工具函数集合
178
+ * 这样就不需要在每个项目中重复包装工具函数
179
+ */
180
+ export function createBoundAuthUtils(instance) {
181
+ const { authStore, tokenStorage, authActions, authClient } = instance;
182
+ return {
183
+ // Store 访问
184
+ getCurrentUser: () => getCurrentUser(authStore),
185
+ getCurrentUserId: () => getCurrentUserId(authStore),
186
+ getCurrentUserIdSafe: () => getCurrentUserIdSafe(authStore),
187
+ isAuthenticated: () => isAuthenticated(authStore),
188
+ isLoading: () => isLoading(authStore),
189
+ isLoaded: () => isLoaded(authStore),
190
+ waitForAuth: () => waitForAuth(authStore),
191
+ // 需要多个参数的函数
192
+ getAuthToken: () => getAuthToken(authStore, tokenStorage, authActions, authClient),
193
+ getAuthHeaders: () => getAuthHeaders(authStore, tokenStorage, authActions, authClient),
194
+ // 已创建的实例
195
+ apiClient: createApiClient(authStore, tokenStorage, authActions, authClient),
196
+ userManager: createUserManager(authStore),
197
+ };
198
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 认证相关的类型定义
3
+ */
4
+ export type SessionUser = {
5
+ banExpires?: string;
6
+ banReason?: string;
7
+ banned?: boolean;
8
+ createdAt: string;
9
+ email: string;
10
+ emailVerified: boolean;
11
+ id: string;
12
+ image?: string;
13
+ lastLoginAt?: string;
14
+ name: string;
15
+ role?: string;
16
+ updatedAt: string;
17
+ };
18
+ export type Session = {
19
+ createdAt: string;
20
+ expiresAt: string;
21
+ id: string;
22
+ ipAddress?: string;
23
+ token: string;
24
+ updatedAt: string;
25
+ user: SessionUser;
26
+ userAgent?: string;
27
+ userId: string;
28
+ };
29
+ export interface AuthState {
30
+ error: string | null;
31
+ isAuthenticated: boolean;
32
+ isLoaded: boolean;
33
+ loading: boolean;
34
+ token: string | null;
35
+ user: SessionUser | null;
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,OAAO,CAAA;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,WAAW,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;CACzB"}
package/dist/types.js ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * 认证相关的类型定义
3
+ */
4
+ export {};
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@choiceform/shared-auth",
3
+ "version": "0.1.0",
4
+ "description": "Shared authentication package for Choiceform projects",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsc --watch",
22
+ "clean": "rimraf dist",
23
+ "prepublishOnly": "pnpm run build"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/choiceform/automation.git",
28
+ "directory": "packages/shared-auth"
29
+ },
30
+ "keywords": [
31
+ "authentication",
32
+ "auth",
33
+ "better-auth",
34
+ "legend-state",
35
+ "react",
36
+ "oauth",
37
+ "github-oauth",
38
+ "choiceform"
39
+ ],
40
+ "license": "MIT",
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "@legendapp/state": "v3.0.0-beta.26",
46
+ "better-auth": "^1.3.8",
47
+ "react": "18.2.0",
48
+ "react-router": "^7.6.3"
49
+ },
50
+ "peerDependencies": {
51
+ "@choiceform/design-system": "^1.2.64",
52
+ "@legendapp/state": "v3.0.0-beta.26",
53
+ "better-auth": "^1.3.8",
54
+ "react": ">=18.0.0",
55
+ "react-dom": ">=18.0.0",
56
+ "react-router": "^7.6.3"
57
+ },
58
+ "devDependencies": {
59
+ "@types/react": "18.2.71",
60
+ "@types/react-dom": "18.2.22",
61
+ "typescript": "^5.5.3",
62
+ "rimraf": "^6.0.1"
63
+ }
64
+ }
65
+