@windrun-huaiin/third-ui 7.1.2 → 7.2.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 (77) hide show
  1. package/dist/clerk/clerk-page-generator-client.d.ts +10 -0
  2. package/dist/clerk/clerk-page-generator-client.js +28 -0
  3. package/dist/clerk/clerk-page-generator-client.mjs +25 -0
  4. package/dist/clerk/clerk-page-generator.js +1 -0
  5. package/dist/clerk/clerk-page-generator.mjs +1 -0
  6. package/dist/clerk/client-page-generator.d.ts +10 -0
  7. package/dist/clerk/client-page-generator.js +28 -0
  8. package/dist/clerk/client-page-generator.mjs +25 -0
  9. package/dist/clerk/context/FingerprintProvider.d.ts +25 -0
  10. package/dist/clerk/context/FingerprintProvider.js +71 -0
  11. package/dist/clerk/context/FingerprintProvider.mjs +65 -0
  12. package/dist/clerk/fingerprint/fingerprint-client.d.ts +47 -0
  13. package/dist/clerk/fingerprint/fingerprint-client.js +183 -0
  14. package/dist/clerk/fingerprint/fingerprint-client.mjs +174 -0
  15. package/dist/clerk/fingerprint/fingerprint-provider.d.ts +25 -0
  16. package/dist/clerk/fingerprint/fingerprint-provider.js +71 -0
  17. package/dist/clerk/fingerprint/fingerprint-provider.mjs +65 -0
  18. package/dist/clerk/fingerprint/fingerprint-server.d.ts +22 -0
  19. package/dist/clerk/fingerprint/fingerprint-server.js +75 -0
  20. package/dist/clerk/fingerprint/fingerprint-server.mjs +71 -0
  21. package/dist/clerk/fingerprint/fingerprint-shared.d.ts +17 -0
  22. package/dist/clerk/fingerprint/fingerprint-shared.js +35 -0
  23. package/dist/clerk/fingerprint/fingerprint-shared.mjs +29 -0
  24. package/dist/clerk/fingerprint/fingerprint.d.ts +55 -0
  25. package/dist/clerk/fingerprint/fingerprint.js +17 -0
  26. package/dist/clerk/fingerprint/fingerprint.mjs +15 -0
  27. package/dist/clerk/fingerprint/index.d.ts +5 -0
  28. package/dist/clerk/fingerprint/index.js +29 -0
  29. package/dist/clerk/fingerprint/index.mjs +5 -0
  30. package/dist/clerk/fingerprint/server.d.ts +3 -0
  31. package/dist/clerk/fingerprint/server.js +15 -0
  32. package/dist/clerk/fingerprint/server.mjs +2 -0
  33. package/dist/clerk/fingerprint/types.d.ts +42 -0
  34. package/dist/clerk/fingerprint/use-fingerprint.d.ts +6 -0
  35. package/dist/clerk/fingerprint/use-fingerprint.js +182 -0
  36. package/dist/clerk/fingerprint/use-fingerprint.mjs +180 -0
  37. package/dist/clerk/fingerprint.d.ts +55 -0
  38. package/dist/clerk/fingerprint.js +237 -0
  39. package/dist/clerk/fingerprint.mjs +225 -0
  40. package/dist/clerk/hooks/useFingerprint.d.ts +6 -0
  41. package/dist/clerk/hooks/useFingerprint.js +182 -0
  42. package/dist/clerk/hooks/useFingerprint.mjs +180 -0
  43. package/dist/clerk/index.d.ts +3 -0
  44. package/dist/clerk/index.js +7 -0
  45. package/dist/clerk/index.mjs +3 -0
  46. package/dist/clerk/signin-with-fingerprint-client.d.ts +7 -0
  47. package/dist/clerk/signin-with-fingerprint-client.js +52 -0
  48. package/dist/clerk/signin-with-fingerprint-client.mjs +47 -0
  49. package/dist/clerk/signup-with-fingerprint-client.d.ts +7 -0
  50. package/dist/clerk/signup-with-fingerprint-client.js +52 -0
  51. package/dist/clerk/signup-with-fingerprint-client.mjs +47 -0
  52. package/dist/clerk/types.d.ts +42 -0
  53. package/dist/fuma/mdx/toc-base.js +1 -1
  54. package/dist/fuma/mdx/toc-base.mjs +1 -1
  55. package/dist/node_modules/.pnpm/@fingerprintjs_fingerprintjs@4.6.2/node_modules/@fingerprintjs/fingerprintjs/dist/fp.esm.js +3245 -0
  56. package/dist/node_modules/.pnpm/@fingerprintjs_fingerprintjs@4.6.2/node_modules/@fingerprintjs/fingerprintjs/dist/fp.esm.mjs +3218 -0
  57. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.2/node_modules/tslib/tslib.es6.js +51 -0
  58. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.2/node_modules/tslib/tslib.es6.mjs +50 -1
  59. package/dist/node_modules/.pnpm/cose-base@1.0.3/node_modules/cose-base/cose-base.js +1 -1
  60. package/dist/node_modules/.pnpm/cose-base@2.2.0/node_modules/cose-base/cose-base.js +1 -1
  61. package/dist/node_modules/.pnpm/layout-base@1.0.2/node_modules/layout-base/layout-base.js +1 -1
  62. package/dist/node_modules/.pnpm/layout-base@2.0.1/node_modules/layout-base/layout-base.js +1 -1
  63. package/package.json +12 -1
  64. package/src/clerk/clerk-page-generator-client.tsx +37 -0
  65. package/src/clerk/clerk-page-generator.tsx +5 -1
  66. package/src/clerk/fingerprint/fingerprint-client.ts +202 -0
  67. package/src/clerk/fingerprint/fingerprint-provider.tsx +114 -0
  68. package/src/clerk/fingerprint/fingerprint-server.ts +88 -0
  69. package/src/clerk/fingerprint/fingerprint-shared.ts +29 -0
  70. package/src/clerk/fingerprint/index.ts +15 -0
  71. package/src/clerk/fingerprint/server.ts +9 -0
  72. package/src/clerk/fingerprint/types.ts +48 -0
  73. package/src/clerk/fingerprint/use-fingerprint.ts +208 -0
  74. package/src/clerk/index.ts +9 -2
  75. package/src/clerk/server.ts +1 -0
  76. package/src/clerk/signin-with-fingerprint-client.tsx +57 -0
  77. package/src/clerk/signup-with-fingerprint-client.tsx +57 -0
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Fingerprint Shared Utilities
3
+ * 客户端和服务端共享的常量、类型和验证逻辑
4
+ */
5
+
6
+ // Fingerprint ID的存储键和header名
7
+ export const FINGERPRINT_STORAGE_KEY = 'diaomao_fingerprint_id';
8
+ export const FINGERPRINT_HEADER_NAME = 'x-fingerprint-id';
9
+ export const FINGERPRINT_COOKIE_NAME = 'fingerprint_id';
10
+
11
+ /**
12
+ * 验证fingerprint ID格式
13
+ * 可以在客户端和服务端使用
14
+ */
15
+ export function isValidFingerprintId(fingerprintId: string): boolean {
16
+ if (!fingerprintId) return false;
17
+ // 支持多种格式:
18
+ // - fp_ + FingerprintJS visitorId (变长字符串)
19
+ // - fp_fallback_ + 时间戳_随机字符串 (客户端降级方案)
20
+ // - fp_server_ + 时间戳_随机字符串 (服务端降级)
21
+ return /^fp(_fallback|_server)?_[a-zA-Z0-9_]+$/.test(fingerprintId);
22
+ }
23
+
24
+ // 常量导出
25
+ export const FINGERPRINT_CONSTANTS = {
26
+ STORAGE_KEY: FINGERPRINT_STORAGE_KEY,
27
+ HEADER_NAME: FINGERPRINT_HEADER_NAME,
28
+ COOKIE_NAME: FINGERPRINT_COOKIE_NAME,
29
+ } as const;
@@ -0,0 +1,15 @@
1
+ 'use client';
2
+
3
+ // Fingerprint system client-side exports
4
+ // This follows the design specification for fingerprint module exports
5
+
6
+ // Shared utilities (can be used in any environment)
7
+ export * from './fingerprint-shared';
8
+ export * from './types';
9
+
10
+ // Client-side utilities (browser only)
11
+ export * from './fingerprint-client';
12
+
13
+ // Client-side hooks and context
14
+ export * from './use-fingerprint';
15
+ export * from './fingerprint-provider';
@@ -0,0 +1,9 @@
1
+ // Fingerprint system server-side exports
2
+ // Server-only utilities for fingerprint ID extraction and validation
3
+
4
+ // Shared utilities (can be used in any environment)
5
+ export * from './fingerprint-shared';
6
+ export * from './types';
7
+
8
+ // Server-side utilities (server only)
9
+ export * from './fingerprint-server';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Fingerprint System Types
3
+ * 指纹识别系统的类型定义
4
+ */
5
+
6
+ export interface AnonymousUser {
7
+ userId: string;
8
+ fingerprintId: string;
9
+ status: string;
10
+ createdAt: string;
11
+ }
12
+
13
+ export interface Credits {
14
+ balanceFree: number;
15
+ balancePaid: number;
16
+ totalBalance: number;
17
+ }
18
+
19
+ export interface FingerprintConfig {
20
+ /** API endpoint for anonymous user initialization */
21
+ apiEndpoint: string;
22
+ /** Whether to automatically initialize the user on load */
23
+ autoInitialize?: boolean;
24
+ /** Initial credits for new users */
25
+ initialCredits?: number;
26
+ }
27
+
28
+ export interface UseFingerprintResult {
29
+ fingerprintId: string | null;
30
+ anonymousUser: AnonymousUser | null;
31
+ credits: Credits | null;
32
+ isLoading: boolean;
33
+ isInitialized: boolean;
34
+ error: string | null;
35
+ initializeAnonymousUser: () => Promise<void>;
36
+ refreshUserData: () => Promise<void>;
37
+ }
38
+
39
+ export interface FingerprintContextType extends UseFingerprintResult {}
40
+
41
+ export interface FingerprintProviderProps {
42
+ children: React.ReactNode;
43
+ config: FingerprintConfig;
44
+ }
45
+ // Fetch wrapper type
46
+ export interface FingerprintFetch {
47
+ (url: string | URL | Request, init?: RequestInit): Promise<Response>;
48
+ }
@@ -0,0 +1,208 @@
1
+ 'use client';
2
+
3
+ import { useState, useEffect, useCallback } from 'react';
4
+ import {
5
+ getOrGenerateFingerprintId,
6
+ getFingerprintId,
7
+ setFingerprintId,
8
+ createFingerprintHeaders
9
+ } from './fingerprint-client';
10
+ import type {
11
+ AnonymousUser,
12
+ Credits,
13
+ UseFingerprintResult,
14
+ FingerprintConfig
15
+ } from './types';
16
+
17
+ /**
18
+ * Hook for managing fingerprint ID and anonymous user data
19
+ * Accepts configuration to customize API endpoint and behavior
20
+ */
21
+ export function useFingerprint(config: FingerprintConfig): UseFingerprintResult {
22
+ const [fingerprintId, setFingerprintIdState] = useState<string | null>(null);
23
+ const [anonymousUser, setAnonymousUser] = useState<AnonymousUser | null>(null);
24
+ const [credits, setCredits] = useState<Credits | null>(null);
25
+ const [isLoading, setIsLoading] = useState(true);
26
+ const [isInitialized, setIsInitialized] = useState(false);
27
+ const [error, setError] = useState<string | null>(null);
28
+
29
+ /**
30
+ * 第一阶段:初始化fingerprint ID
31
+ */
32
+ const initializeFingerprintId = useCallback(async () => {
33
+ if (typeof window === 'undefined') return null;
34
+
35
+ try {
36
+ // 优先检查现有ID
37
+ const existingId = getFingerprintId();
38
+ if (existingId) {
39
+ setFingerprintIdState(existingId);
40
+ return existingId;
41
+ }
42
+
43
+ // 生成新的fingerprint ID
44
+ const currentFingerprintId = await getOrGenerateFingerprintId();
45
+ setFingerprintIdState(currentFingerprintId);
46
+ return currentFingerprintId;
47
+ } catch (error) {
48
+ console.error('Failed to initialize fingerprint ID:', error);
49
+ setError('Failed to generate fingerprint ID');
50
+ return null;
51
+ }
52
+ }, []);
53
+
54
+ /**
55
+ * 第二阶段:初始化匿名用户
56
+ */
57
+ const initializeAnonymousUser = useCallback(async () => {
58
+ if (!fingerprintId) {
59
+ console.warn('Cannot initialize user without fingerprint ID');
60
+ return;
61
+ }
62
+
63
+ try {
64
+ setIsLoading(true);
65
+ setError(null);
66
+
67
+ const fingerprintHeaders = await createFingerprintHeaders();
68
+ const response = await fetch(config.apiEndpoint, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ ...fingerprintHeaders,
73
+ },
74
+ body: JSON.stringify({
75
+ fingerprintId: fingerprintId,
76
+ }),
77
+ });
78
+
79
+ if (!response.ok) {
80
+ const errorData = await response.json().catch(() => ({}));
81
+ throw new Error(errorData.error || 'Failed to initialize anonymous user');
82
+ }
83
+
84
+ const data = await response.json();
85
+
86
+ if (data.success) {
87
+ setAnonymousUser(data.user);
88
+ setCredits(data.credits);
89
+ setIsInitialized(true);
90
+
91
+ // 确保fingerprint ID同步
92
+ if (data.user.fingerprintId !== fingerprintId) {
93
+ setFingerprintId(data.user.fingerprintId);
94
+ setFingerprintIdState(data.user.fingerprintId);
95
+ }
96
+ } else {
97
+ throw new Error(data.error || 'Unknown error occurred');
98
+ }
99
+ } catch (err) {
100
+ console.error('Failed to initialize anonymous user:', err);
101
+ setError(err instanceof Error ? err.message : 'Unknown error');
102
+ } finally {
103
+ setIsLoading(false);
104
+ }
105
+ }, [fingerprintId]);
106
+
107
+ /**
108
+ * 刷新用户数据
109
+ */
110
+ const refreshUserData = useCallback(async () => {
111
+ if (!fingerprintId) return;
112
+
113
+ try {
114
+ setError(null);
115
+
116
+ const fingerprintHeaders = await createFingerprintHeaders();
117
+ const response = await fetch(`${config.apiEndpoint}?fingerprintId=${fingerprintId}`, {
118
+ method: 'GET',
119
+ headers: fingerprintHeaders,
120
+ });
121
+
122
+ if (!response.ok) {
123
+ if (response.status === 404) {
124
+ // 用户不存在,需要重新初始化
125
+ await initializeAnonymousUser();
126
+ return;
127
+ }
128
+ throw new Error('Failed to fetch user data');
129
+ }
130
+
131
+ const data = await response.json();
132
+
133
+ if (data.success) {
134
+ setAnonymousUser(data.user);
135
+ setCredits(data.credits);
136
+ }
137
+ } catch (err) {
138
+ console.error('Failed to refresh user data:', err);
139
+ setError(err instanceof Error ? err.message : 'Unknown error');
140
+ }
141
+ }, [fingerprintId, initializeAnonymousUser, config.apiEndpoint]);
142
+
143
+ /**
144
+ * 检查现有用户数据(仅在有fingerprint ID时执行)
145
+ */
146
+ const checkExistingUser = useCallback(async () => {
147
+ if (!fingerprintId) return;
148
+
149
+ try {
150
+ const fingerprintHeaders = await createFingerprintHeaders();
151
+ const response = await fetch(`${config.apiEndpoint}?fingerprintId=${fingerprintId}`, {
152
+ method: 'GET',
153
+ headers: fingerprintHeaders,
154
+ });
155
+
156
+ if (response.ok) {
157
+ const data = await response.json();
158
+ if (data.success) {
159
+ setAnonymousUser(data.user);
160
+ setCredits(data.credits);
161
+ setIsInitialized(true);
162
+ }
163
+ }
164
+ } catch (err) {
165
+ console.error('Failed to check existing user:', err);
166
+ }
167
+ }, [fingerprintId, config.apiEndpoint]);
168
+
169
+ // 第一阶段:页面加载完成后生成指纹ID
170
+ useEffect(() => {
171
+ if (typeof window === 'undefined') return;
172
+
173
+ const initFingerprint = async () => {
174
+ await initializeFingerprintId();
175
+ setIsLoading(false); // 第一阶段完成,结束加载状态
176
+ };
177
+
178
+ initFingerprint();
179
+ }, [initializeFingerprintId]);
180
+
181
+ // 第二阶段:有指纹ID后检查现有用户
182
+ useEffect(() => {
183
+ if (!fingerprintId || isInitialized) return;
184
+
185
+ checkExistingUser();
186
+ }, [fingerprintId, isInitialized, checkExistingUser]);
187
+
188
+ // 第三阶段:如果没有现有用户且自动初始化开启,则创建新用户
189
+ useEffect(() => {
190
+ if (!fingerprintId || isInitialized || isLoading || error) return;
191
+ if (config.autoInitialize === false) return;
192
+
193
+ initializeAnonymousUser();
194
+ }, [fingerprintId, isInitialized, isLoading, error, initializeAnonymousUser, config.autoInitialize]);
195
+
196
+ return {
197
+ fingerprintId,
198
+ anonymousUser,
199
+ credits,
200
+ isLoading,
201
+ isInitialized,
202
+ error,
203
+ initializeAnonymousUser,
204
+ refreshUserData,
205
+ };
206
+ }
207
+
208
+ // createFingerprintFetch moved to fingerprint.ts
@@ -1,3 +1,10 @@
1
1
  'use client';
2
- // Clerk related components
3
- export * from './clerk-provider-client';
2
+ // Client-side exports
3
+ export * from './clerk-provider-client';
4
+
5
+ // Fingerprint-enhanced Clerk components (client-side)
6
+ export * from './signup-with-fingerprint-client';
7
+ export * from './signin-with-fingerprint-client';
8
+
9
+ // Client-side page generators
10
+ export * from './clerk-page-generator-client';
@@ -1,3 +1,4 @@
1
+ // Server-side exports - safe for SSR
1
2
  export * from './clerk-page-generator';
2
3
  export * from './clerk-user';
3
4
  export * from './clerk-organization';
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import { SignIn } from '@clerk/nextjs';
4
+ import { useEffect } from 'react';
5
+ import { useFingerprintContextSafe } from './fingerprint/fingerprint-provider';
6
+
7
+ /**
8
+ * SignIn component with fingerprint awareness
9
+ * 如果没有FingerprintProvider,会优雅降级为普通SignIn组件
10
+ * 如果有FingerprintProvider,会处理fingerprint相关逻辑
11
+ */
12
+ export function SignInWithFingerprint() {
13
+ const fingerprintContext = useFingerprintContextSafe();
14
+
15
+ // 如果没有fingerprint context,使用默认值
16
+ const {
17
+ fingerprintId = null,
18
+ anonymousUser = null,
19
+ isInitialized = false,
20
+ initializeAnonymousUser = async () => {}
21
+ } = fingerprintContext || {};
22
+
23
+ // 准备传递给Clerk的metadata,包含匿名用户信息
24
+ const unsafeMetadata = {
25
+ user_id: anonymousUser?.userId || null, // 数据库中的user_id
26
+ fingerprint_id: fingerprintId || null, // 浏览器指纹ID
27
+ };
28
+
29
+ // 确保匿名用户已初始化
30
+ useEffect(() => {
31
+ if (!isInitialized && fingerprintId) {
32
+ initializeAnonymousUser();
33
+ }
34
+ }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
+
36
+ // 调试日志和处理登录逻辑
37
+ useEffect(() => {
38
+ console.log('SignInWithFingerprint Debug:', {
39
+ fingerprintProvider: fingerprintContext ? 'Available' : 'Not found',
40
+ fingerprintId: fingerprintId || 'Not generated',
41
+ anonymousUser: anonymousUser ? 'Initialized' : 'Not initialized',
42
+ clerkMetadata: unsafeMetadata
43
+ });
44
+
45
+ if (anonymousUser && fingerprintId) {
46
+ console.log('User signed in with existing anonymous data:', {
47
+ anonymousUserId: anonymousUser.userId,
48
+ fingerprintId,
49
+ });
50
+ // TODO: 实现数据合并逻辑
51
+ }
52
+ }, [anonymousUser, fingerprintId, fingerprintContext, unsafeMetadata]);
53
+
54
+ return <SignIn unsafeMetadata={unsafeMetadata} />;
55
+ }
56
+
57
+ export default SignInWithFingerprint;
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+
3
+ import { SignUp } from '@clerk/nextjs';
4
+ import { useEffect } from 'react';
5
+ import { useFingerprintContextSafe } from './fingerprint/fingerprint-provider';
6
+
7
+ /**
8
+ * SignUp component with fingerprint awareness
9
+ * 如果没有FingerprintProvider,会优雅降级为普通SignUp组件
10
+ * 如果有FingerprintProvider,会处理fingerprint相关逻辑
11
+ */
12
+ export function SignUpWithFingerprint() {
13
+ const fingerprintContext = useFingerprintContextSafe();
14
+
15
+ // 如果没有fingerprint context,使用默认值
16
+ const {
17
+ fingerprintId = null,
18
+ anonymousUser = null,
19
+ isInitialized = false,
20
+ initializeAnonymousUser = async () => {}
21
+ } = fingerprintContext || {};
22
+
23
+ // 准备传递给Clerk的metadata,包含匿名用户信息
24
+ const unsafeMetadata = {
25
+ user_id: anonymousUser?.userId || null, // 数据库中的user_id
26
+ fingerprint_id: fingerprintId || null, // 浏览器指纹ID
27
+ };
28
+
29
+ // 确保匿名用户已初始化
30
+ useEffect(() => {
31
+ if (!isInitialized && fingerprintId) {
32
+ initializeAnonymousUser();
33
+ }
34
+ }, [fingerprintId, isInitialized, initializeAnonymousUser]);
35
+
36
+ // 调试日志和处理注册逻辑
37
+ useEffect(() => {
38
+ console.log('SignUpWithFingerprint Debug:', {
39
+ fingerprintProvider: fingerprintContext ? 'Available' : 'Not found',
40
+ fingerprintId: fingerprintId || 'Not generated',
41
+ anonymousUser: anonymousUser ? 'Initialized' : 'Not initialized',
42
+ clerkMetadata: unsafeMetadata
43
+ });
44
+
45
+ if (anonymousUser && fingerprintId) {
46
+ console.log('User signed up with existing anonymous data:', {
47
+ anonymousUserId: anonymousUser.userId,
48
+ fingerprintId,
49
+ });
50
+ // TODO: 实现数据迁移逻辑
51
+ }
52
+ }, [anonymousUser, fingerprintId, fingerprintContext, unsafeMetadata]);
53
+
54
+ return <SignUp unsafeMetadata={unsafeMetadata} />;
55
+ }
56
+
57
+ export default SignUpWithFingerprint;