@dangao/bun-server 1.0.0 → 1.0.3
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/package.json +4 -2
- package/readme.md +163 -2
- package/src/auth/controller.ts +148 -0
- package/src/auth/decorators.ts +81 -0
- package/src/auth/index.ts +12 -0
- package/src/auth/jwt.ts +169 -0
- package/src/auth/oauth2.ts +244 -0
- package/src/auth/types.ts +248 -0
- package/src/cache/cache-module.ts +67 -0
- package/src/cache/decorators.ts +202 -0
- package/src/cache/index.ts +27 -0
- package/src/cache/service.ts +151 -0
- package/src/cache/types.ts +420 -0
- package/src/config/config-module.ts +76 -0
- package/src/config/index.ts +8 -0
- package/src/config/service.ts +93 -0
- package/src/config/types.ts +27 -0
- package/src/controller/controller.ts +251 -0
- package/src/controller/decorators.ts +84 -0
- package/src/controller/index.ts +7 -0
- package/src/controller/metadata.ts +27 -0
- package/src/controller/param-binder.ts +157 -0
- package/src/core/application.ts +233 -0
- package/src/core/context.ts +228 -0
- package/src/core/index.ts +4 -0
- package/src/core/server.ts +128 -0
- package/src/core/types.ts +2 -0
- package/src/database/connection-manager.ts +239 -0
- package/src/database/connection-pool.ts +322 -0
- package/src/database/database-extension.ts +62 -0
- package/src/database/database-module.ts +115 -0
- package/src/database/health-indicator.ts +51 -0
- package/src/database/index.ts +47 -0
- package/src/database/orm/decorators.ts +155 -0
- package/src/database/orm/drizzle-repository.ts +39 -0
- package/src/database/orm/index.ts +23 -0
- package/src/database/orm/repository-decorator.ts +39 -0
- package/src/database/orm/repository.ts +103 -0
- package/src/database/orm/service.ts +49 -0
- package/src/database/orm/transaction-decorator.ts +45 -0
- package/src/database/orm/transaction-interceptor.ts +243 -0
- package/src/database/orm/transaction-manager.ts +276 -0
- package/src/database/orm/transaction-types.ts +140 -0
- package/src/database/orm/types.ts +99 -0
- package/src/database/service.ts +221 -0
- package/src/database/types.ts +171 -0
- package/src/di/container.ts +398 -0
- package/src/di/decorators.ts +228 -0
- package/src/di/index.ts +4 -0
- package/src/di/module-registry.ts +188 -0
- package/src/di/module.ts +65 -0
- package/src/di/types.ts +67 -0
- package/src/error/error-codes.ts +222 -0
- package/src/error/filter.ts +43 -0
- package/src/error/handler.ts +66 -0
- package/src/error/http-exception.ts +115 -0
- package/src/error/i18n.ts +217 -0
- package/src/error/index.ts +16 -0
- package/src/extensions/index.ts +5 -0
- package/src/extensions/logger-extension.ts +31 -0
- package/src/extensions/logger-module.ts +69 -0
- package/src/extensions/types.ts +14 -0
- package/src/files/index.ts +5 -0
- package/src/files/static-middleware.ts +53 -0
- package/src/files/storage.ts +67 -0
- package/src/files/types.ts +33 -0
- package/src/files/upload-middleware.ts +45 -0
- package/src/health/controller.ts +76 -0
- package/src/health/health-module.ts +51 -0
- package/src/health/index.ts +12 -0
- package/src/health/types.ts +28 -0
- package/src/index.ts +270 -0
- package/src/metrics/collector.ts +209 -0
- package/src/metrics/controller.ts +40 -0
- package/src/metrics/index.ts +15 -0
- package/src/metrics/metrics-module.ts +58 -0
- package/src/metrics/middleware.ts +46 -0
- package/src/metrics/prometheus.ts +79 -0
- package/src/metrics/types.ts +103 -0
- package/src/middleware/builtin/cors.ts +60 -0
- package/src/middleware/builtin/error-handler.ts +90 -0
- package/src/middleware/builtin/file-upload.ts +42 -0
- package/src/middleware/builtin/index.ts +14 -0
- package/src/middleware/builtin/logger.ts +91 -0
- package/src/middleware/builtin/rate-limit.ts +252 -0
- package/src/middleware/builtin/static-file.ts +88 -0
- package/src/middleware/decorators.ts +91 -0
- package/src/middleware/index.ts +11 -0
- package/src/middleware/middleware.ts +13 -0
- package/src/middleware/pipeline.ts +93 -0
- package/src/queue/decorators.ts +110 -0
- package/src/queue/index.ts +26 -0
- package/src/queue/queue-module.ts +64 -0
- package/src/queue/service.ts +302 -0
- package/src/queue/types.ts +341 -0
- package/src/request/body-parser.ts +133 -0
- package/src/request/file-handler.ts +46 -0
- package/src/request/index.ts +5 -0
- package/src/request/request.ts +107 -0
- package/src/request/response.ts +150 -0
- package/src/router/decorators.ts +122 -0
- package/src/router/index.ts +6 -0
- package/src/router/registry.ts +98 -0
- package/src/router/route.ts +140 -0
- package/src/router/router.ts +241 -0
- package/src/router/types.ts +27 -0
- package/src/security/access-decision-manager.ts +34 -0
- package/src/security/authentication-manager.ts +47 -0
- package/src/security/context.ts +92 -0
- package/src/security/filter.ts +162 -0
- package/src/security/index.ts +8 -0
- package/src/security/providers/index.ts +3 -0
- package/src/security/providers/jwt-provider.ts +60 -0
- package/src/security/providers/oauth2-provider.ts +70 -0
- package/src/security/security-module.ts +145 -0
- package/src/security/types.ts +165 -0
- package/src/session/decorators.ts +45 -0
- package/src/session/index.ts +19 -0
- package/src/session/middleware.ts +143 -0
- package/src/session/service.ts +218 -0
- package/src/session/session-module.ts +69 -0
- package/src/session/types.ts +373 -0
- package/src/swagger/decorators.ts +133 -0
- package/src/swagger/generator.ts +234 -0
- package/src/swagger/index.ts +7 -0
- package/src/swagger/swagger-extension.ts +41 -0
- package/src/swagger/swagger-module.ts +83 -0
- package/src/swagger/types.ts +188 -0
- package/src/swagger/ui.ts +98 -0
- package/src/testing/harness.ts +96 -0
- package/src/validation/decorators.ts +95 -0
- package/src/validation/errors.ts +28 -0
- package/src/validation/index.ts +14 -0
- package/src/validation/types.ts +35 -0
- package/src/validation/validator.ts +63 -0
- package/src/websocket/decorators.ts +51 -0
- package/src/websocket/index.ts +12 -0
- package/src/websocket/registry.ts +133 -0
- package/tests/cache/cache-module.test.ts +212 -0
- package/tests/config/config-module.test.ts +151 -0
- package/tests/controller/controller.test.ts +189 -0
- package/tests/core/application.test.ts +57 -0
- package/tests/core/context-body.test.ts +44 -0
- package/tests/core/context.test.ts +86 -0
- package/tests/core/edge-cases.test.ts +432 -0
- package/tests/database/database-module.test.ts +385 -0
- package/tests/database/orm.test.ts +164 -0
- package/tests/database/postgres-mysql-integration.test.ts +395 -0
- package/tests/database/transaction.test.ts +238 -0
- package/tests/di/container.test.ts +264 -0
- package/tests/di/module.test.ts +128 -0
- package/tests/error/error-codes.test.ts +121 -0
- package/tests/error/error-handler.test.ts +68 -0
- package/tests/error/error-handling.test.ts +254 -0
- package/tests/error/http-exception.test.ts +37 -0
- package/tests/error/i18n-integration.test.ts +175 -0
- package/tests/extensions/logger-extension.test.ts +40 -0
- package/tests/files/static-middleware.test.ts +67 -0
- package/tests/files/upload-middleware.test.ts +43 -0
- package/tests/health/health-module.test.ts +116 -0
- package/tests/integration/application-router.test.ts +85 -0
- package/tests/integration/body-parsing.test.ts +88 -0
- package/tests/integration/cache-e2e.test.ts +114 -0
- package/tests/integration/oauth2-e2e.test.ts +615 -0
- package/tests/integration/session-e2e.test.ts +207 -0
- package/tests/metrics/metrics-module.test.ts +178 -0
- package/tests/middleware/builtin.test.ts +206 -0
- package/tests/middleware/file-upload.test.ts +41 -0
- package/tests/middleware/middleware.test.ts +120 -0
- package/tests/middleware/pipeline.test.ts +72 -0
- package/tests/middleware/rate-limit.test.ts +314 -0
- package/tests/middleware/static-file.test.ts +62 -0
- package/tests/perf/harness.test.ts +48 -0
- package/tests/perf/optimization.test.ts +183 -0
- package/tests/perf/regression.test.ts +120 -0
- package/tests/queue/queue-module.test.ts +217 -0
- package/tests/request/body-parser.test.ts +96 -0
- package/tests/request/response.test.ts +99 -0
- package/tests/router/decorators.test.ts +48 -0
- package/tests/router/registry.test.ts +51 -0
- package/tests/router/route.test.ts +71 -0
- package/tests/router/router-normalization.test.ts +106 -0
- package/tests/router/router.test.ts +133 -0
- package/tests/security/access-decision-manager.test.ts +84 -0
- package/tests/security/authentication-manager.test.ts +81 -0
- package/tests/security/context.test.ts +302 -0
- package/tests/security/filter.test.ts +225 -0
- package/tests/security/jwt-provider.test.ts +106 -0
- package/tests/security/oauth2-provider.test.ts +269 -0
- package/tests/security/security-module.test.ts +143 -0
- package/tests/session/session-module.test.ts +307 -0
- package/tests/stress/di-stress.test.ts +30 -0
- package/tests/swagger/decorators.test.ts +153 -0
- package/tests/swagger/generator.test.ts +202 -0
- package/tests/swagger/swagger-extension.test.ts +72 -0
- package/tests/swagger/swagger-module.test.ts +79 -0
- package/tests/utils/test-port.ts +10 -0
- package/tests/validation/controller-validation.test.ts +64 -0
- package/tests/validation/validation.test.ts +42 -0
- package/tests/websocket/gateway.test.ts +68 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 缓存装饰器元数据键
|
|
5
|
+
*/
|
|
6
|
+
const CACHEABLE_METADATA_KEY = Symbol('@dangao/bun-server:cache:cacheable');
|
|
7
|
+
const CACHE_EVICT_METADATA_KEY = Symbol('@dangao/bun-server:cache:cache-evict');
|
|
8
|
+
const CACHE_PUT_METADATA_KEY = Symbol('@dangao/bun-server:cache:cache-put');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 缓存配置
|
|
12
|
+
*/
|
|
13
|
+
export interface CacheableOptions {
|
|
14
|
+
/**
|
|
15
|
+
* 缓存键(支持 SpEL 表达式,如 'user:{id}')
|
|
16
|
+
*/
|
|
17
|
+
key?: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 缓存键前缀
|
|
21
|
+
*/
|
|
22
|
+
keyPrefix?: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* TTL(毫秒),0 表示永不过期
|
|
26
|
+
*/
|
|
27
|
+
ttl?: number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 条件表达式(如果返回 false,则不缓存)
|
|
31
|
+
* 支持 SpEL 表达式,如 'result.status === "success"'
|
|
32
|
+
*/
|
|
33
|
+
condition?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 缓存清除配置
|
|
38
|
+
*/
|
|
39
|
+
export interface CacheEvictOptions {
|
|
40
|
+
/**
|
|
41
|
+
* 缓存键(支持 SpEL 表达式)
|
|
42
|
+
*/
|
|
43
|
+
key?: string;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 缓存键前缀
|
|
47
|
+
*/
|
|
48
|
+
keyPrefix?: string;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 是否在方法执行前清除
|
|
52
|
+
* @default false
|
|
53
|
+
*/
|
|
54
|
+
beforeInvocation?: boolean;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 是否清除所有匹配的键(支持通配符)
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
allEntries?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 缓存更新配置
|
|
65
|
+
*/
|
|
66
|
+
export interface CachePutOptions {
|
|
67
|
+
/**
|
|
68
|
+
* 缓存键(支持 SpEL 表达式)
|
|
69
|
+
*/
|
|
70
|
+
key?: string;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 缓存键前缀
|
|
74
|
+
*/
|
|
75
|
+
keyPrefix?: string;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* TTL(毫秒),0 表示永不过期
|
|
79
|
+
*/
|
|
80
|
+
ttl?: number;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 条件表达式(如果返回 false,则不更新缓存)
|
|
84
|
+
*/
|
|
85
|
+
condition?: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 缓存装饰器元数据
|
|
90
|
+
*/
|
|
91
|
+
export interface CacheableMetadata {
|
|
92
|
+
key?: string;
|
|
93
|
+
keyPrefix?: string;
|
|
94
|
+
ttl?: number;
|
|
95
|
+
condition?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface CacheEvictMetadata {
|
|
99
|
+
key?: string;
|
|
100
|
+
keyPrefix?: string;
|
|
101
|
+
beforeInvocation?: boolean;
|
|
102
|
+
allEntries?: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface CachePutMetadata {
|
|
106
|
+
key?: string;
|
|
107
|
+
keyPrefix?: string;
|
|
108
|
+
ttl?: number;
|
|
109
|
+
condition?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 缓存方法结果
|
|
114
|
+
* @param options - 缓存配置
|
|
115
|
+
*/
|
|
116
|
+
export function Cacheable(options: CacheableOptions = {}): MethodDecorator {
|
|
117
|
+
return function (
|
|
118
|
+
target: unknown,
|
|
119
|
+
propertyKey: string | symbol,
|
|
120
|
+
descriptor: PropertyDescriptor,
|
|
121
|
+
) {
|
|
122
|
+
const metadata: CacheableMetadata = {
|
|
123
|
+
key: options.key,
|
|
124
|
+
keyPrefix: options.keyPrefix,
|
|
125
|
+
ttl: options.ttl,
|
|
126
|
+
condition: options.condition,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
Reflect.defineMetadata(
|
|
130
|
+
CACHEABLE_METADATA_KEY,
|
|
131
|
+
metadata,
|
|
132
|
+
descriptor.value,
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 清除缓存
|
|
139
|
+
* @param options - 清除配置
|
|
140
|
+
*/
|
|
141
|
+
export function CacheEvict(options: CacheEvictOptions = {}): MethodDecorator {
|
|
142
|
+
return function (
|
|
143
|
+
target: unknown,
|
|
144
|
+
propertyKey: string | symbol,
|
|
145
|
+
descriptor: PropertyDescriptor,
|
|
146
|
+
) {
|
|
147
|
+
const metadata: CacheEvictMetadata = {
|
|
148
|
+
key: options.key,
|
|
149
|
+
keyPrefix: options.keyPrefix,
|
|
150
|
+
beforeInvocation: options.beforeInvocation ?? false,
|
|
151
|
+
allEntries: options.allEntries ?? false,
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
Reflect.defineMetadata(
|
|
155
|
+
CACHE_EVICT_METADATA_KEY,
|
|
156
|
+
metadata,
|
|
157
|
+
descriptor.value,
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 更新缓存
|
|
164
|
+
* @param options - 更新配置
|
|
165
|
+
*/
|
|
166
|
+
export function CachePut(options: CachePutOptions = {}): MethodDecorator {
|
|
167
|
+
return function (
|
|
168
|
+
target: unknown,
|
|
169
|
+
propertyKey: string | symbol,
|
|
170
|
+
descriptor: PropertyDescriptor,
|
|
171
|
+
) {
|
|
172
|
+
const metadata: CachePutMetadata = {
|
|
173
|
+
key: options.key,
|
|
174
|
+
keyPrefix: options.keyPrefix,
|
|
175
|
+
ttl: options.ttl,
|
|
176
|
+
condition: options.condition,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
Reflect.defineMetadata(CACHE_PUT_METADATA_KEY, metadata, descriptor.value);
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 获取缓存装饰器元数据
|
|
185
|
+
*/
|
|
186
|
+
export function getCacheableMetadata(
|
|
187
|
+
target: unknown,
|
|
188
|
+
): CacheableMetadata | undefined {
|
|
189
|
+
return Reflect.getMetadata(CACHEABLE_METADATA_KEY, target as object);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function getCacheEvictMetadata(
|
|
193
|
+
target: unknown,
|
|
194
|
+
): CacheEvictMetadata | undefined {
|
|
195
|
+
return Reflect.getMetadata(CACHE_EVICT_METADATA_KEY, target as object);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function getCachePutMetadata(
|
|
199
|
+
target: unknown,
|
|
200
|
+
): CachePutMetadata | undefined {
|
|
201
|
+
return Reflect.getMetadata(CACHE_PUT_METADATA_KEY, target as object);
|
|
202
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export { CacheModule } from './cache-module';
|
|
2
|
+
export { CacheService } from './service';
|
|
3
|
+
export {
|
|
4
|
+
Cacheable,
|
|
5
|
+
CacheEvict,
|
|
6
|
+
CachePut,
|
|
7
|
+
getCacheableMetadata,
|
|
8
|
+
getCacheEvictMetadata,
|
|
9
|
+
getCachePutMetadata,
|
|
10
|
+
type CacheableOptions,
|
|
11
|
+
type CacheEvictOptions,
|
|
12
|
+
type CachePutOptions,
|
|
13
|
+
type CacheableMetadata,
|
|
14
|
+
type CacheEvictMetadata,
|
|
15
|
+
type CachePutMetadata,
|
|
16
|
+
} from './decorators';
|
|
17
|
+
export {
|
|
18
|
+
MemoryCacheStore,
|
|
19
|
+
RedisCacheStore,
|
|
20
|
+
CACHE_SERVICE_TOKEN,
|
|
21
|
+
CACHE_OPTIONS_TOKEN,
|
|
22
|
+
} from './types';
|
|
23
|
+
export type {
|
|
24
|
+
CacheStore,
|
|
25
|
+
CacheModuleOptions,
|
|
26
|
+
RedisCacheStoreOptions,
|
|
27
|
+
} from './types';
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Injectable } from '../di/decorators';
|
|
2
|
+
import type { CacheStore, CacheModuleOptions } from './types';
|
|
3
|
+
import { CACHE_OPTIONS_TOKEN } from './types';
|
|
4
|
+
import { Inject } from '../di/decorators';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 缓存服务
|
|
8
|
+
*/
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class CacheService {
|
|
11
|
+
private store: CacheStore;
|
|
12
|
+
private defaultTtl: number;
|
|
13
|
+
private keyPrefix: string;
|
|
14
|
+
|
|
15
|
+
public constructor(
|
|
16
|
+
@Inject(CACHE_OPTIONS_TOKEN) options: CacheModuleOptions,
|
|
17
|
+
) {
|
|
18
|
+
this.store = options.store!;
|
|
19
|
+
this.defaultTtl = options.defaultTtl ?? 3600000; // 1 小时
|
|
20
|
+
this.keyPrefix = options.keyPrefix ?? '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 获取缓存值
|
|
25
|
+
* @param key - 缓存键
|
|
26
|
+
* @returns 缓存值,如果不存在则返回 undefined
|
|
27
|
+
*/
|
|
28
|
+
public async get<T = unknown>(key: string): Promise<T | undefined> {
|
|
29
|
+
return this.store.get<T>(this.getKey(key));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 设置缓存值
|
|
34
|
+
* @param key - 缓存键
|
|
35
|
+
* @param value - 缓存值
|
|
36
|
+
* @param ttl - 过期时间(毫秒),0 表示永不过期,undefined 使用默认 TTL
|
|
37
|
+
* @returns 是否设置成功
|
|
38
|
+
*/
|
|
39
|
+
public async set<T = unknown>(
|
|
40
|
+
key: string,
|
|
41
|
+
value: T,
|
|
42
|
+
ttl?: number,
|
|
43
|
+
): Promise<boolean> {
|
|
44
|
+
const finalTtl = ttl !== undefined ? ttl : this.defaultTtl;
|
|
45
|
+
return this.store.set(this.getKey(key), value, finalTtl);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 删除缓存
|
|
50
|
+
* @param key - 缓存键
|
|
51
|
+
* @returns 是否删除成功
|
|
52
|
+
*/
|
|
53
|
+
public async delete(key: string): Promise<boolean> {
|
|
54
|
+
return this.store.delete(this.getKey(key));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 检查缓存是否存在
|
|
59
|
+
* @param key - 缓存键
|
|
60
|
+
* @returns 是否存在
|
|
61
|
+
*/
|
|
62
|
+
public async has(key: string): Promise<boolean> {
|
|
63
|
+
return this.store.has(this.getKey(key));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 清空所有缓存
|
|
68
|
+
* @returns 是否清空成功
|
|
69
|
+
*/
|
|
70
|
+
public async clear(): Promise<boolean> {
|
|
71
|
+
return this.store.clear();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 获取多个缓存值
|
|
76
|
+
* @param keys - 缓存键数组
|
|
77
|
+
* @returns 缓存值映射
|
|
78
|
+
*/
|
|
79
|
+
public async getMany<T = unknown>(
|
|
80
|
+
keys: string[],
|
|
81
|
+
): Promise<Map<string, T>> {
|
|
82
|
+
const prefixedKeys = keys.map((k) => this.getKey(k));
|
|
83
|
+
const result = await this.store.getMany<T>(prefixedKeys);
|
|
84
|
+
|
|
85
|
+
// 移除前缀
|
|
86
|
+
const map = new Map<string, T>();
|
|
87
|
+
for (const [key, value] of result.entries()) {
|
|
88
|
+
map.set(key.replace(this.keyPrefix, ''), value);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return map;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 设置多个缓存值
|
|
96
|
+
* @param entries - 缓存条目数组
|
|
97
|
+
* @param ttl - 过期时间(毫秒),0 表示永不过期,undefined 使用默认 TTL
|
|
98
|
+
* @returns 是否设置成功
|
|
99
|
+
*/
|
|
100
|
+
public async setMany<T = unknown>(
|
|
101
|
+
entries: Array<{ key: string; value: T }>,
|
|
102
|
+
ttl?: number,
|
|
103
|
+
): Promise<boolean> {
|
|
104
|
+
const finalTtl = ttl !== undefined ? ttl : this.defaultTtl;
|
|
105
|
+
const prefixedEntries = entries.map(({ key, value }) => ({
|
|
106
|
+
key: this.getKey(key),
|
|
107
|
+
value,
|
|
108
|
+
}));
|
|
109
|
+
return this.store.setMany(prefixedEntries, finalTtl);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 删除多个缓存
|
|
114
|
+
* @param keys - 缓存键数组
|
|
115
|
+
* @returns 删除成功的键数组
|
|
116
|
+
*/
|
|
117
|
+
public async deleteMany(keys: string[]): Promise<string[]> {
|
|
118
|
+
const prefixedKeys = keys.map((k) => this.getKey(k));
|
|
119
|
+
const deleted = await this.store.deleteMany(prefixedKeys);
|
|
120
|
+
return deleted.map((k) => k.replace(this.keyPrefix, ''));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 获取或设置缓存(如果不存在则执行函数并缓存结果)
|
|
125
|
+
* @param key - 缓存键
|
|
126
|
+
* @param factory - 值工厂函数
|
|
127
|
+
* @param ttl - 过期时间(毫秒),0 表示永不过期,undefined 使用默认 TTL
|
|
128
|
+
* @returns 缓存值
|
|
129
|
+
*/
|
|
130
|
+
public async getOrSet<T = unknown>(
|
|
131
|
+
key: string,
|
|
132
|
+
factory: () => Promise<T> | T,
|
|
133
|
+
ttl?: number,
|
|
134
|
+
): Promise<T> {
|
|
135
|
+
const cached = await this.get<T>(key);
|
|
136
|
+
if (cached !== undefined) {
|
|
137
|
+
return cached;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const value = await factory();
|
|
141
|
+
await this.set(key, value, ttl);
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 获取带前缀的键
|
|
147
|
+
*/
|
|
148
|
+
private getKey(key: string): string {
|
|
149
|
+
return this.keyPrefix ? `${this.keyPrefix}${key}` : key;
|
|
150
|
+
}
|
|
151
|
+
}
|