@lobehub/lobehub 2.0.0-next.161 → 2.0.0-next.163

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 (36) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/changelog/v1.json +14 -0
  3. package/locales/ar/authError.json +40 -0
  4. package/locales/bg-BG/authError.json +40 -0
  5. package/locales/de-DE/authError.json +40 -0
  6. package/locales/en-US/authError.json +40 -0
  7. package/locales/es-ES/authError.json +40 -0
  8. package/locales/fa-IR/authError.json +40 -0
  9. package/locales/fr-FR/authError.json +40 -0
  10. package/locales/it-IT/authError.json +40 -0
  11. package/locales/ja-JP/authError.json +40 -0
  12. package/locales/ko-KR/authError.json +40 -0
  13. package/locales/nl-NL/authError.json +40 -0
  14. package/locales/pl-PL/authError.json +40 -0
  15. package/locales/pt-BR/authError.json +40 -0
  16. package/locales/ru-RU/authError.json +40 -0
  17. package/locales/tr-TR/authError.json +40 -0
  18. package/locales/vi-VN/authError.json +40 -0
  19. package/locales/zh-CN/authError.json +40 -0
  20. package/locales/zh-CN/setting.json +2 -2
  21. package/locales/zh-TW/authError.json +40 -0
  22. package/package.json +1 -1
  23. package/src/app/[variants]/(auth)/auth-error/page.tsx +59 -0
  24. package/src/app/[variants]/(main)/discover/(list)/_layout/Mobile/Nav.tsx +13 -1
  25. package/src/app/[variants]/(main)/discover/(list)/features/Pagination.tsx +6 -2
  26. package/src/app/[variants]/(main)/discover/components/Title.tsx +22 -2
  27. package/src/auth.ts +13 -48
  28. package/src/envs/redis.ts +1 -1
  29. package/src/libs/better-auth/utils/config.ts +91 -0
  30. package/src/libs/redis/manager.ts +5 -1
  31. package/src/libs/redis/redis.test.ts +1 -1
  32. package/src/libs/redis/upstash.test.ts +9 -5
  33. package/src/libs/redis/upstash.ts +44 -20
  34. package/src/locales/default/authError.ts +40 -0
  35. package/src/locales/default/index.ts +2 -0
  36. package/src/proxy.ts +1 -0
@@ -5,7 +5,7 @@
5
5
  //
6
6
  // Read more here: https://github.com/capricorn86/happy-dom/issues/1042#issuecomment-3585851354
7
7
  import { Buffer } from 'node:buffer';
8
- import { describe, expect, it, vi } from 'vitest';
8
+ import { afterEach, describe, expect, it, vi } from 'vitest';
9
9
 
10
10
  import { UpstashConfig } from './types';
11
11
 
@@ -139,9 +139,9 @@ describe('mocked', () => {
139
139
  await provider.hset(bufKey, 'field', 'value');
140
140
  await provider.del(bufKey);
141
141
 
142
- expect(mocks.mockSet).toHaveBeenCalledWith('buffer-key', 'value', undefined);
143
- expect(mocks.mockHset).toHaveBeenCalledWith('buffer-key', { field: 'value' });
144
- expect(mocks.mockDel).toHaveBeenCalledWith('buffer-key');
142
+ expect(mocks.mockSet).toHaveBeenCalledWith('mock:buffer-key', 'value', undefined);
143
+ expect(mocks.mockHset).toHaveBeenCalledWith('mock:buffer-key', { field: 'value' });
144
+ expect(mocks.mockDel).toHaveBeenCalledWith('mock:buffer-key');
145
145
  });
146
146
 
147
147
  it('passes set options through to upstash client', async () => {
@@ -149,6 +149,10 @@ describe('mocked', () => {
149
149
 
150
150
  await provider.set('key', 'value', { ex: 10, nx: true, get: true });
151
151
 
152
- expect(mocks.mockSet).toHaveBeenCalledWith('key', 'value', { ex: 10, nx: true, get: true });
152
+ expect(mocks.mockSet).toHaveBeenCalledWith('mock:key', 'value', {
153
+ ex: 10,
154
+ nx: true,
155
+ get: true,
156
+ });
153
157
  });
154
158
  });
@@ -20,9 +20,28 @@ import {
20
20
  export class UpstashRedisProvider implements BaseRedisProvider {
21
21
  provider: 'upstash' = 'upstash';
22
22
  private client: Redis;
23
+ private readonly prefix: string;
23
24
 
24
25
  constructor(options: UpstashConfig | RedisConfigNodejs) {
25
- this.client = new Redis(options as RedisConfigNodejs);
26
+ const { prefix, ...clientOptions } = options as UpstashConfig & RedisConfigNodejs;
27
+ this.prefix = prefix ? `${prefix}:` : '';
28
+ this.client = new Redis(clientOptions as RedisConfigNodejs);
29
+ }
30
+
31
+ /**
32
+ * Build a fully qualified key assuming the input was already normalized.
33
+ * Avoids re-running normalization when callers have normalized keys (e.g. mset).
34
+ */
35
+ private addPrefixToKey(normalizedKey: string) {
36
+ return `${this.prefix}${normalizedKey}`;
37
+ }
38
+
39
+ private buildKey(key: RedisKey) {
40
+ return this.addPrefixToKey(normalizeRedisKey(key));
41
+ }
42
+
43
+ private buildKeys(keys: RedisKey[]) {
44
+ return normalizeRedisKeys(keys).map((key) => `${this.prefix}${key}`);
26
45
  }
27
46
 
28
47
  async initialize(): Promise<void> {
@@ -34,15 +53,11 @@ export class UpstashRedisProvider implements BaseRedisProvider {
34
53
  }
35
54
 
36
55
  async get(key: RedisKey): Promise<string | null> {
37
- return this.client.get(normalizeRedisKey(key));
56
+ return this.client.get(this.buildKey(key));
38
57
  }
39
58
 
40
59
  async set(key: RedisKey, value: RedisValue, options?: SetOptions): Promise<RedisSetResult> {
41
- const res = await this.client.set(
42
- normalizeRedisKey(key),
43
- value,
44
- buildUpstashSetOptions(options),
45
- );
60
+ const res = await this.client.set(this.buildKey(key), value, buildUpstashSetOptions(options));
46
61
  if (Buffer.isBuffer(res)) {
47
62
  return res.toString();
48
63
  }
@@ -51,55 +66,64 @@ export class UpstashRedisProvider implements BaseRedisProvider {
51
66
  }
52
67
 
53
68
  async setex(key: RedisKey, seconds: number, value: RedisValue): Promise<'OK'> {
54
- return this.client.setex(normalizeRedisKey(key), seconds, value);
69
+ return this.client.setex(this.buildKey(key), seconds, value);
55
70
  }
56
71
 
57
72
  async del(...keys: RedisKey[]): Promise<number> {
58
- return this.client.del(...normalizeRedisKeys(keys));
73
+ return this.client.del(...this.buildKeys(keys));
59
74
  }
60
75
 
61
76
  async exists(...keys: RedisKey[]): Promise<number> {
62
- return this.client.exists(...normalizeRedisKeys(keys));
77
+ return this.client.exists(...this.buildKeys(keys));
63
78
  }
64
79
 
65
80
  async expire(key: RedisKey, seconds: number): Promise<number> {
66
- return this.client.expire(normalizeRedisKey(key), seconds);
81
+ return this.client.expire(this.buildKey(key), seconds);
67
82
  }
68
83
 
69
84
  async ttl(key: RedisKey): Promise<number> {
70
- return this.client.ttl(normalizeRedisKey(key));
85
+ return this.client.ttl(this.buildKey(key));
71
86
  }
72
87
 
73
88
  async incr(key: RedisKey): Promise<number> {
74
- return this.client.incr(normalizeRedisKey(key));
89
+ return this.client.incr(this.buildKey(key));
75
90
  }
76
91
 
77
92
  async decr(key: RedisKey): Promise<number> {
78
- return this.client.decr(normalizeRedisKey(key));
93
+ return this.client.decr(this.buildKey(key));
79
94
  }
80
95
 
81
96
  async mget(...keys: RedisKey[]): Promise<(string | null)[]> {
82
- return this.client.mget(...normalizeRedisKeys(keys));
97
+ return this.client.mget(...this.buildKeys(keys));
83
98
  }
84
99
 
85
100
  async mset(values: RedisMSetArgument): Promise<'OK'> {
86
- return this.client.mset(normalizeMsetValues(values));
101
+ const normalized = normalizeMsetValues(values);
102
+ const prefixed = Object.entries(normalized).reduce<Record<string, RedisValue>>(
103
+ (acc, [key, value]) => {
104
+ acc[this.addPrefixToKey(key)] = value;
105
+ return acc;
106
+ },
107
+ {},
108
+ );
109
+
110
+ return this.client.mset(prefixed);
87
111
  }
88
112
 
89
113
  async hget(key: RedisKey, field: RedisKey): Promise<string | null> {
90
- return this.client.hget(normalizeRedisKey(key), normalizeRedisKey(field));
114
+ return this.client.hget(this.buildKey(key), normalizeRedisKey(field));
91
115
  }
92
116
 
93
117
  async hset(key: RedisKey, field: RedisKey, value: RedisValue): Promise<number> {
94
- return this.client.hset(normalizeRedisKey(key), { [normalizeRedisKey(field)]: value });
118
+ return this.client.hset(this.buildKey(key), { [normalizeRedisKey(field)]: value });
95
119
  }
96
120
 
97
121
  async hdel(key: RedisKey, ...fields: RedisKey[]): Promise<number> {
98
- return this.client.hdel(normalizeRedisKey(key), ...normalizeRedisKeys(fields));
122
+ return this.client.hdel(this.buildKey(key), ...normalizeRedisKeys(fields));
99
123
  }
100
124
 
101
125
  async hgetall(key: RedisKey): Promise<Record<string, string>> {
102
- const res = await this.client.hgetall(normalizeRedisKey(key));
126
+ const res = await this.client.hgetall(this.buildKey(key));
103
127
  if (!res) {
104
128
  return {};
105
129
  }
@@ -0,0 +1,40 @@
1
+ export default {
2
+ actions: {
3
+ discord: '前往 Discord 反馈',
4
+ home: '返回首页',
5
+ retry: '重新登录',
6
+ },
7
+ codes: {
8
+ ACCOUNT_ALREADY_LINKED_TO_DIFFERENT_USER: '该账号已关联至其他用户',
9
+ ACCOUNT_NOT_FOUND: '未找到对应账号',
10
+ CREDENTIAL_ACCOUNT_NOT_FOUND: '凭证账号不存在',
11
+ EMAIL_CAN_NOT_BE_UPDATED: '当前账号邮箱不可修改',
12
+ EMAIL_NOT_VERIFIED: '请先完成邮箱验证',
13
+ FAILED_TO_CREATE_SESSION: '创建会话失败',
14
+ FAILED_TO_CREATE_USER: '创建用户失败',
15
+ FAILED_TO_GET_SESSION: '获取会话失败',
16
+ FAILED_TO_GET_USER_INFO: '获取用户信息失败',
17
+ FAILED_TO_UNLINK_LAST_ACCOUNT: '无法解绑最后一个关联账号',
18
+ FAILED_TO_UPDATE_USER: '更新用户信息失败',
19
+ ID_TOKEN_NOT_SUPPORTED: '当前身份令牌不被支持',
20
+ INVALID_EMAIL: '邮箱格式不正确',
21
+ INVALID_EMAIL_OR_PASSWORD: '邮箱或密码错误',
22
+ INVALID_PASSWORD: '密码格式无效',
23
+ INVALID_TOKEN: '令牌无效或已过期',
24
+ PASSWORD_TOO_LONG: '密码长度过长',
25
+ PASSWORD_TOO_SHORT: '密码长度过短',
26
+ PROVIDER_NOT_FOUND: '未找到对应的身份提供方配置',
27
+ RATE_LIMIT_EXCEEDED: '请求过于频繁,请稍后再试',
28
+ SESSION_EXPIRED: '会话已过期,请重新登录',
29
+ SOCIAL_ACCOUNT_ALREADY_LINKED: '该社交账号已被其他用户绑定',
30
+ UNEXPECTED_ERROR: '发生未知错误,请重试',
31
+ UNKNOWN: '发生未知错误,请重试或联系支持',
32
+ USER_ALREADY_EXISTS: '用户已存在',
33
+ USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL: '邮箱已被使用,请尝试其他邮箱',
34
+ USER_ALREADY_HAS_PASSWORD: '该账号已设置密码',
35
+ USER_BANNED: '该用户已被封禁',
36
+ USER_EMAIL_NOT_FOUND: '未找到对应邮箱',
37
+ USER_NOT_FOUND: '未找到用户',
38
+ },
39
+ title: '身份验证出错',
40
+ };
@@ -1,4 +1,5 @@
1
1
  import auth from './auth';
2
+ import authError from './authError';
2
3
  import changelog from './changelog';
3
4
  import chat from './chat';
4
5
  import clerk from './clerk';
@@ -33,6 +34,7 @@ import welcome from './welcome';
33
34
 
34
35
  const resources = {
35
36
  auth,
37
+ authError,
36
38
  changelog,
37
39
  chat,
38
40
  clerk,
package/src/proxy.ts CHANGED
@@ -52,6 +52,7 @@ export const config = {
52
52
  '/signin(.*)',
53
53
  '/verify-email(.*)',
54
54
  '/reset-password(.*)',
55
+ '/auth-error(.*)',
55
56
  '/next-auth/(.*)',
56
57
  '/oauth(.*)',
57
58
  '/oidc(.*)',