@ubean/server 0.1.13 → 0.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 (56) hide show
  1. package/dist/analytics-entry.d.ts +2 -0
  2. package/dist/analytics-entry.js +2 -0
  3. package/dist/cache-C84ix1Vq.js +173 -0
  4. package/dist/cache-b-MZlyv0.d.ts +48 -0
  5. package/dist/cache-directive-C1Nekkza.js +304 -0
  6. package/dist/cache-directive-CAxJAQyE.d.ts +175 -0
  7. package/dist/cache-directive.d.ts +2 -0
  8. package/dist/cache-directive.js +2 -0
  9. package/dist/cache-entry.d.ts +3 -0
  10. package/dist/cache-entry.js +3 -0
  11. package/dist/cron-entry.d.ts +2 -0
  12. package/dist/cron-entry.js +2 -0
  13. package/dist/cron-scheduler-BF33PPn4.d.ts +77 -0
  14. package/dist/cron-scheduler-BVuXv7nn.js +258 -0
  15. package/dist/database-CfpFznl-.d.ts +67 -0
  16. package/dist/database-DNrY44SQ.js +352 -0
  17. package/dist/database.d.ts +2 -0
  18. package/dist/database.js +2 -0
  19. package/dist/email-BjfRiR9b.js +354 -0
  20. package/dist/email-BvpEuNn_.d.ts +226 -0
  21. package/dist/email.d.ts +2 -0
  22. package/dist/email.js +2 -0
  23. package/dist/feature-flags-CdLwsMD2.js +657 -0
  24. package/dist/feature-flags-DWkS6p0D.d.ts +386 -0
  25. package/dist/fetch-memo-rbkxxnW4.js +338 -0
  26. package/dist/index.d.ts +183 -488
  27. package/dist/index.js +352 -2023
  28. package/dist/middleware.d.ts +2 -0
  29. package/dist/middleware.js +3 -0
  30. package/dist/observability-Cio6Qq1H.js +339 -0
  31. package/dist/observability-DUNUEjj3.d.ts +70 -0
  32. package/dist/observability.d.ts +2 -0
  33. package/dist/observability.js +2 -0
  34. package/dist/queue-Bwzi3mhK.js +210 -0
  35. package/dist/queue-GOfTAWlz.d.ts +55 -0
  36. package/dist/queue.d.ts +2 -0
  37. package/dist/queue.js +2 -0
  38. package/dist/realtime.d.ts +2 -0
  39. package/dist/realtime.js +2 -0
  40. package/dist/security.d.ts +2 -0
  41. package/dist/security.js +2 -0
  42. package/dist/sessions-BLqFFQTL.d.ts +217 -0
  43. package/dist/sessions-BsBsyFAG.js +450 -0
  44. package/dist/single-flight-BJyhDLdU.d.ts +422 -0
  45. package/dist/single-flight-mJ4ZKbx1.js +715 -0
  46. package/dist/sse-Ct72zhic.d.ts +95 -0
  47. package/dist/sse-a6Ky9Vcl.js +310 -0
  48. package/dist/static-DPHaovQe.js +90 -0
  49. package/dist/static-K2dRvjpS.d.ts +11 -0
  50. package/dist/static.d.ts +2 -0
  51. package/dist/static.js +2 -0
  52. package/dist/storage-BZLMaqHr.js +162 -0
  53. package/dist/storage-QdlPtPtR.d.ts +48 -0
  54. package/dist/storage.d.ts +2 -0
  55. package/dist/storage.js +2 -0
  56. package/package.json +68 -6
@@ -0,0 +1,422 @@
1
+ import { Context, MiddlewareHandler } from "hono";
2
+ import { UbeanEnv } from "@ubean/shared";
3
+ //#region src/cors.d.ts
4
+ interface CorsOptions {
5
+ origin?: string | string[] | boolean | ((origin: string, c: Context<UbeanEnv>) => boolean | string | undefined | Promise<boolean | string | undefined>);
6
+ allowMethods?: string[];
7
+ allowHeaders?: string[];
8
+ exposeHeaders?: string[];
9
+ credentials?: boolean;
10
+ maxAge?: number;
11
+ preflightContinue?: boolean;
12
+ }
13
+ declare function createCorsMiddleware(options?: CorsOptions): MiddlewareHandler<UbeanEnv>;
14
+ declare function defineCors(options: CorsOptions): MiddlewareHandler<UbeanEnv>;
15
+ //#endregion
16
+ //#region src/rate-limit.d.ts
17
+ interface RateLimitOptions {
18
+ maxRequests?: number;
19
+ windowMs?: number;
20
+ keyGenerator?: (c: Context<UbeanEnv>) => string;
21
+ handler?: (c: Context<UbeanEnv>, info: RateLimitInfo) => Response | Promise<Response>;
22
+ skip?: (c: Context<UbeanEnv>) => boolean | Promise<boolean>;
23
+ standardHeaders?: boolean;
24
+ legacyHeaders?: boolean;
25
+ store?: RateLimitStore;
26
+ }
27
+ interface RateLimitInfo {
28
+ limit: number;
29
+ remaining: number;
30
+ reset: number;
31
+ retryAfter: number;
32
+ }
33
+ interface RateLimitStoreEntry {
34
+ count: number;
35
+ resetAt: number;
36
+ }
37
+ interface RateLimitStore {
38
+ get(key: string): Promise<RateLimitStoreEntry | undefined>;
39
+ set(key: string, entry: RateLimitStoreEntry, ttlMs: number): Promise<void>;
40
+ increment(key: string, windowMs: number): Promise<RateLimitStoreEntry>;
41
+ reset(key: string): Promise<void>;
42
+ }
43
+ declare function createRateLimitMiddleware(options?: RateLimitOptions): MiddlewareHandler<UbeanEnv>;
44
+ declare function defineRateLimit(options: RateLimitOptions): MiddlewareHandler<UbeanEnv>;
45
+ declare function createMemoryRateLimitStore(): RateLimitStore & {
46
+ destroy(): void;
47
+ };
48
+ //#endregion
49
+ //#region src/after.d.ts
50
+ type AfterCallback = () => void | Promise<void>;
51
+ /**
52
+ * 注册一个在响应发送后执行的回调
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * import { after } from 'ubean';
57
+ *
58
+ * export const POST = defineHandler(async (c) => {
59
+ * const result = doWork();
60
+ * after(() => {
61
+ * // 这些不会阻塞响应
62
+ * analytics.track('post_created', result);
63
+ * invalidateCache('/posts');
64
+ * });
65
+ * return c.json(result);
66
+ * });
67
+ * ```
68
+ */
69
+ declare function after(callback: AfterCallback): void;
70
+ /**
71
+ * 创建 after() 中间件
72
+ *
73
+ * 在响应发送后执行所有通过 `after()` 注册的回调
74
+ */
75
+ declare function createAfterMiddleware(): MiddlewareHandler<UbeanEnv>;
76
+ /**
77
+ * 手动执行 after 回调(用于自定义中间件或测试)
78
+ */
79
+ declare function flushAfterCallbacks(c: Context<UbeanEnv>): Promise<void>;
80
+ /**
81
+ * 获取当前请求中注册的 after 回调数量(主要用于测试)
82
+ */
83
+ declare function getAfterCallbackCount(c?: Context<UbeanEnv>): number;
84
+ //#endregion
85
+ //#region src/fetch-memo.d.ts
86
+ /**
87
+ * 创建 fetch memoization 中间件
88
+ *
89
+ * 在请求作用域内包装 globalThis.fetch,对相同 GET URL 自动去重
90
+ */
91
+ declare function createFetchMemoizationMiddleware(options?: {
92
+ /** 自定义哪些 URL 不参与 memoization */
93
+ exclude?: (url: string) => boolean;
94
+ /** 是否跳过非 GET 请求(默认 true,即非 GET 不 memoize) */
95
+ skipNonGet?: boolean;
96
+ }): MiddlewareHandler<UbeanEnv>;
97
+ /**
98
+ * 手动创建一个 memoized fetch 函数(不依赖中间件/AsyncLocalStorage)
99
+ *
100
+ * 适用于在非请求上下文中手动使用 memoization
101
+ */
102
+ declare function createMemoizedFetch(options?: {
103
+ originalFetch?: typeof globalThis.fetch;
104
+ ttl?: number;
105
+ }): {
106
+ fetch: typeof globalThis.fetch;
107
+ clear: () => void;
108
+ size: () => number;
109
+ };
110
+ /**
111
+ * fetch Data Cache 选项(对齐 Next.js `next` 字段)。
112
+ *
113
+ * 仅当 fetch 的 `init.next` 包含 `revalidate` 或 `tags` 时启用跨请求缓存;
114
+ * 无 `next` 选项或 `noStore: true` 时不缓存(默认行为不变)。
115
+ */
116
+ interface FetchCacheOptions {
117
+ /** TTL(秒)。0 = 不缓存;`Infinity` / 未定义 = 永久缓存(直到被失效)。 */
118
+ revalidate?: number;
119
+ /** 关联标签列表(用于 `revalidateTag(tag)` 失效)。 */
120
+ tags?: string[];
121
+ /** 显式退出缓存(等价于 `revalidate: 0`)。 */
122
+ noStore?: boolean;
123
+ }
124
+ /** 持有 Next.js 风格 `next` 选项的 RequestInit 扩展。 */
125
+ interface FetchInitWithNext extends RequestInit {
126
+ /** Next.js 风格的 fetch 缓存控制选项。 */
127
+ next?: FetchCacheOptions;
128
+ }
129
+ /** Data Cache 中间件选项。 */
130
+ interface DataCacheMiddlewareOptions {
131
+ /**
132
+ * 是否为开发模式(默认 `process.env.NODE_ENV !== 'production'`)。
133
+ * dev 模式下默认不缓存(便于开发时看到最新数据),可通过 `forceDevCache` 强制启用。
134
+ */
135
+ dev?: boolean;
136
+ /** dev 模式下也启用缓存(用于测试)。 */
137
+ forceDevCache?: boolean;
138
+ /** 自定义 URL 排除规则(返回 true 的 URL 不缓存)。 */
139
+ exclude?: (url: string) => boolean;
140
+ }
141
+ /**
142
+ * 创建 fetch Data Cache 中间件(Task 4)。
143
+ *
144
+ * 在请求作用域内包装 `globalThis.fetch`,对带 `next: { revalidate, tags }` 选项的
145
+ * GET/HEAD 请求按 TTL 跨请求缓存响应。无 `next` 选项的请求走原始路径(默认行为不变)。
146
+ *
147
+ * 行为:
148
+ * - 仅缓存 2xx 响应(4xx/5xx 不缓存,允许后续重试)
149
+ * - dev 模式默认 no-cache(可通过 `forceDevCache` 强制启用,用于测试)
150
+ * - 与 `revalidateTag` / `revalidatePath` 集成,失效对应缓存条目
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * import { createDataCacheMiddleware } from '@ubean/server';
155
+ * app.use('*', createDataCacheMiddleware());
156
+ *
157
+ * // 路由处理器中:
158
+ * const res = await fetch('https://api.example.com/data', {
159
+ * next: { revalidate: 60, tags: ['data'] }
160
+ * });
161
+ * ```
162
+ */
163
+ declare function createDataCacheMiddleware(options?: DataCacheMiddlewareOptions): MiddlewareHandler<UbeanEnv>;
164
+ /**
165
+ * 失效所有带指定标签的 Data Cache 条目。返回删除数量。
166
+ *
167
+ * 用户通常无需直接调用 —— `cache-directive.ts` 的 `revalidateTag` 会自动调用此函数。
168
+ */
169
+ declare function revalidateDataCacheTag(tag: string): Promise<number>;
170
+ /**
171
+ * 失效缓存键匹配指定模式的 Data Cache 条目。返回删除数量。
172
+ *
173
+ * 用户通常无需直接调用 —— `cache-directive.ts` 的 `revalidatePath` 会自动调用此函数。
174
+ */
175
+ declare function revalidateDataCachePath(pattern: string | RegExp): Promise<number>;
176
+ /** 清空所有 fetch Data Cache 条目(主要用于测试)。 */
177
+ declare function clearFetchDataCache(): void;
178
+ /** 返回 Data Cache 当前条目数(主要用于测试)。 */
179
+ declare function getDataCacheSize(): number;
180
+ //#endregion
181
+ //#region src/draft-mode.d.ts
182
+ interface DraftModeOptions {
183
+ /** cookie 名称,默认 'ubean_draft' */
184
+ cookieName?: string;
185
+ /** 签名密钥(必填,用于防止 cookie 篡改) */
186
+ secret: string;
187
+ /** cookie 有效期(秒),默认 3600(1 小时) */
188
+ ttl?: number;
189
+ /** cookie 选项 */
190
+ cookie?: {
191
+ path?: string;
192
+ secure?: boolean;
193
+ httpOnly?: boolean;
194
+ sameSite?: 'strict' | 'lax' | 'none';
195
+ domain?: string;
196
+ };
197
+ /** 跳过中间件的路径前缀 */
198
+ exclude?: string[];
199
+ }
200
+ interface DraftMode {
201
+ /** 是否已启用 draft mode */
202
+ readonly isEnabled: boolean;
203
+ /** 启用 draft mode(设置签名 cookie) */
204
+ enable: () => void;
205
+ /** 禁用 draft mode(清除 cookie) */
206
+ disable: () => void;
207
+ }
208
+ /**
209
+ * 创建 draft mode 中间件
210
+ *
211
+ * 中间件读取请求中的签名 cookie,验证签名与过期时间后在 context 上
212
+ * 标记 draft mode 状态。响应阶段根据 controller 的 pendingAction
213
+ * 设置或清除 cookie。
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * // 启用 draft mode(默认 1 小时有效)
218
+ * app.use('*', createDraftModeMiddleware({ secret: 'my-secret' }));
219
+ *
220
+ * // 自定义 cookie 名称与 TTL
221
+ * app.use('*', createDraftModeMiddleware({
222
+ * secret: 'my-secret',
223
+ * cookieName: 'preview',
224
+ * ttl: 86400
225
+ * }));
226
+ * ```
227
+ */
228
+ declare function createDraftModeMiddleware(options: DraftModeOptions): MiddlewareHandler<UbeanEnv>;
229
+ /**
230
+ * 启用 draft mode(设置签名 cookie)
231
+ *
232
+ * 在路由处理函数中调用,中间件会在响应阶段设置 cookie。
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * app.get('/api/preview/enable', c => {
237
+ * enableDraftMode(c);
238
+ * return c.json({ ok: true });
239
+ * });
240
+ * ```
241
+ */
242
+ declare function enableDraftMode(c: Context<UbeanEnv>): void;
243
+ /**
244
+ * 禁用 draft mode(清除 cookie)
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * app.get('/api/preview/disable', c => {
249
+ * disableDraftMode(c);
250
+ * return c.json({ ok: true });
251
+ * });
252
+ * ```
253
+ */
254
+ declare function disableDraftMode(c: Context<UbeanEnv>): void;
255
+ /**
256
+ * 检查 draft mode 是否已启用(从 context 读取)
257
+ *
258
+ * 未注册中间件时返回 false。
259
+ */
260
+ declare function isDraftMode(c: Context<UbeanEnv>): boolean;
261
+ /**
262
+ * 获取 draft mode 组合式 API
263
+ *
264
+ * 返回 `{ isEnabled, enable, disable }`,在路由处理函数中使用。
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * app.get('*', c => {
269
+ * const draft = useDraftMode(c);
270
+ * if (draft.isEnabled) {
271
+ * // 返回草稿内容
272
+ * }
273
+ * return c.json({ draft: draft.isEnabled });
274
+ * });
275
+ * ```
276
+ */
277
+ declare function useDraftMode(c: Context<UbeanEnv>): DraftMode;
278
+ /**
279
+ * 定义 draft mode 中间件(别名,与 defineCsrf / defineCors 风格一致)
280
+ */
281
+ declare function defineDraftMode(options: DraftModeOptions): MiddlewareHandler<UbeanEnv>;
282
+ //#endregion
283
+ //#region src/single-flight.d.ts
284
+ /** 重新获取键 —— 字符串标识符,用于匹配 invalidate() 与 defineRevalidation() */
285
+ type RevalidationKey = string;
286
+ /**
287
+ * 重新获取上下文,传递给每个 revalidation fetcher。
288
+ */
289
+ interface RevalidationContext {
290
+ /** 触发本次重新获取的键列表(invalidate 调用的键与该 entry 的键的交集) */
291
+ keys: RevalidationKey[];
292
+ /** Hono 上下文(用于读取请求信息、session 等) */
293
+ context: Context<UbeanEnv>;
294
+ }
295
+ /**
296
+ * Revalidation fetcher —— 返回需要打包进响应的重新获取数据。
297
+ *
298
+ * 返回值必须是一个扁平对象 `Record<string, unknown>`,其键是客户端缓存键,
299
+ * 值是重新获取的数据。多个 fetcher 的返回值会被合并到同一个 bundle 中。
300
+ */
301
+ type RevalidationFetcher = (ctx: RevalidationContext) => Promise<Record<string, unknown>>;
302
+ /**
303
+ * 已注册的 revalidation 条目。
304
+ */
305
+ interface RevalidationEntry {
306
+ /** 该 fetcher 负责的重新获取键列表 */
307
+ keys: RevalidationKey[];
308
+ /** 重新获取处理器 */
309
+ fetcher: RevalidationFetcher;
310
+ /** 可选名称(用于调试) */
311
+ name?: string;
312
+ }
313
+ /**
314
+ * 单个 revalidation 结果条目。
315
+ */
316
+ interface RevalidationResult {
317
+ /** 重新获取的数据(已合并) */
318
+ data: Record<string, unknown>;
319
+ /** 被重新获取的键 */
320
+ keys: RevalidationKey[];
321
+ /** 时间戳(ms) */
322
+ timestamp: number;
323
+ /** fetcher 执行中产生的错误(若有) */
324
+ errors: Array<{
325
+ keys: RevalidationKey[];
326
+ message: string;
327
+ }>;
328
+ }
329
+ /**
330
+ * Single-flight 中间件选项。
331
+ */
332
+ interface SingleFlightOptions {
333
+ /** 标记响应包含 revalidation 数据的 header 名称 */
334
+ revalidationHeader?: string;
335
+ /** JSON 响应体中存放 revalidation 数据的字段名 */
336
+ revalidationField?: string;
337
+ /** 只处理这些 Content-Type 的响应(默认 application/json) */
338
+ contentTypes?: string[];
339
+ /** 跳过函数 —— 返回 true 则不处理该请求 */
340
+ skip?: (c: Context<UbeanEnv>) => boolean | Promise<boolean>;
341
+ /** revalidation fetcher 是否并行执行(默认 true) */
342
+ parallel?: boolean;
343
+ }
344
+ /**
345
+ * 注册一个 revalidation 依赖。
346
+ *
347
+ * @param keys 该 fetcher 负责的重新获取键列表
348
+ * @param fetcher 重新获取处理器,返回需要打包进响应的数据
349
+ * @param name 可选名称(用于调试)
350
+ *
351
+ * @example
352
+ * ```typescript
353
+ * defineRevalidation(['users', 'user-count'], async (ctx) => {
354
+ * const [users, count] = await Promise.all([
355
+ * db.query.users.findMany(),
356
+ * db.select({ count: count() }).from(users)
357
+ * ]);
358
+ * return { users, 'user-count': count };
359
+ * });
360
+ * ```
361
+ */
362
+ declare function defineRevalidation(keys: RevalidationKey[], fetcher: RevalidationFetcher, name?: string): RevalidationEntry;
363
+ /**
364
+ * 取消注册一个 revalidation 条目。
365
+ */
366
+ declare function unregisterRevalidation(entry: RevalidationEntry): boolean;
367
+ /**
368
+ * 获取所有已注册的 revalidation 条目(只读副本,用于测试/调试)。
369
+ */
370
+ declare function getRevalidationEntries(): RevalidationEntry[];
371
+ /**
372
+ * 清空所有 revalidation 注册(主要用于测试)。
373
+ */
374
+ declare function clearRevalidationRegistry(): void;
375
+ /**
376
+ * 标记需要重新获取的依赖键。
377
+ *
378
+ * 必须在 single-flight 中间件作用域内(action 处理器中)调用,
379
+ * 否则给出开发警告。
380
+ *
381
+ * @example
382
+ * ```typescript
383
+ * export const deleteUser = defineAction(async (input) => {
384
+ * await db.delete(users).where(eq(users.id, input.id));
385
+ * invalidate(['users', `user:${input.id}`]);
386
+ * return { ok: true };
387
+ * });
388
+ * ```
389
+ */
390
+ declare function invalidate(keys: RevalidationKey[]): void;
391
+ /**
392
+ * 标记单个键需要重新获取(`invalidate([key])` 的简写)。
393
+ */
394
+ declare function invalidateKey(key: RevalidationKey): void;
395
+ /**
396
+ * 获取当前请求中被 invalidate 的键(主要用于测试/调试)。
397
+ */
398
+ declare function getInvalidatedKeys(c?: Context<UbeanEnv>): RevalidationKey[];
399
+ /**
400
+ * 创建 single-flight mutations 中间件。
401
+ *
402
+ * 拦截 Server Action 响应,执行由 `invalidate()` 标记的 revalidation,
403
+ * 将结果打包进响应体,使客户端在单个 round-trip 内获得更新后的数据。
404
+ *
405
+ * @example
406
+ * ```typescript
407
+ * app.use('*', createSingleFlightMiddleware());
408
+ * ```
409
+ */
410
+ declare function createSingleFlightMiddleware(options?: SingleFlightOptions): MiddlewareHandler<UbeanEnv>;
411
+ /**
412
+ * 手动执行 revalidation(用于自定义中间件或测试)。
413
+ *
414
+ * 在中间件作用域外也可调用 —— 直接传入 invalidated 键与上下文。
415
+ */
416
+ declare function runRevalidation(invalidatedKeys: RevalidationKey[], c: Context<UbeanEnv>, parallel?: boolean): Promise<RevalidationResult>;
417
+ /**
418
+ * Single-flight 中间件别名(与 cors/rate-limit 的 define* 风格一致)。
419
+ */
420
+ declare function defineSingleFlight(options?: SingleFlightOptions): MiddlewareHandler<UbeanEnv>;
421
+ //#endregion
422
+ export { createFetchMemoizationMiddleware as A, RateLimitOptions as B, isDraftMode as C, FetchInitWithNext as D, FetchCacheOptions as E, after as F, defineRateLimit as G, RateLimitStoreEntry as H, createAfterMiddleware as I, defineCors as J, CorsOptions as K, flushAfterCallbacks as L, getDataCacheSize as M, revalidateDataCachePath as N, clearFetchDataCache as O, revalidateDataCacheTag as P, getAfterCallbackCount as R, enableDraftMode as S, DataCacheMiddlewareOptions as T, createMemoryRateLimitStore as U, RateLimitStore as V, createRateLimitMiddleware as W, DraftMode as _, RevalidationResult as a, defineDraftMode as b, createSingleFlightMiddleware as c, getInvalidatedKeys as d, getRevalidationEntries as f, unregisterRevalidation as g, runRevalidation as h, RevalidationKey as i, createMemoizedFetch as j, createDataCacheMiddleware as k, defineRevalidation as l, invalidateKey as m, RevalidationEntry as n, SingleFlightOptions as o, invalidate as p, createCorsMiddleware as q, RevalidationFetcher as r, clearRevalidationRegistry as s, RevalidationContext as t, defineSingleFlight as u, DraftModeOptions as v, useDraftMode as w, disableDraftMode as x, createDraftModeMiddleware as y, RateLimitInfo as z };