weifuwu 0.55.0 → 0.55.2
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/README.md +103 -8
- package/dist/client/app.d.ts +7 -7
- package/dist/client/i18n.d.ts +5 -1
- package/dist/client/index.d.ts +6 -3
- package/dist/client/middleware/api.d.ts +5 -1
- package/dist/client/middleware/auth.d.ts +5 -1
- package/dist/client/middleware/ws.d.ts +11 -1
- package/dist/client/router.d.ts +14 -1
- package/dist/client/type-flow.test.d.ts +7 -0
- package/dist/client/types.d.ts +6 -1
- package/dist/client/vnode.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/postgres/types.d.ts +15 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ createApp()
|
|
|
150
150
|
|------|---------|------|
|
|
151
151
|
| `weifuwu/client` | `https://unpkg.com/weifuwu@latest/dist/client/index.js` | 客户端核心(createApp, h, 路由, 状态管理等) |
|
|
152
152
|
| `weifuwu/components` | `https://unpkg.com/weifuwu@latest/dist/components/index.js` | 41 个 UI 组件(Button, Card, Table, Modal 等) |
|
|
153
|
-
| 组件样式 | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS +
|
|
153
|
+
| 组件样式 | `https://unpkg.com/weifuwu@latest/dist/components/style.css` | 组件 CSS + 82 个主题 Token + 35 个布局原语 |
|
|
154
154
|
| 独立布局系统 | `https://unpkg.com/weifuwu@latest/dist/layout/weifuwu-layout.css` | 仅 CSS 布局,不依赖 JS |
|
|
155
155
|
|
|
156
156
|
|
|
@@ -179,7 +179,7 @@ createApp()
|
|
|
179
179
|
| `weifuwu/client` | **lockScroll/trapFocus** | 滚动锁定 / 焦点陷阱工具 | — |
|
|
180
180
|
| `weifuwu/client` | **popup** | 弹层 fixed 定位工具(`computeFixedPos` / `computeFixedPosRect`) | — |
|
|
181
181
|
| `weifuwu/components` | **42 个组件** | Button/Table/Modal/Confirm/Toast/... + `confirm()` / `toast()` 命令式中间件 | weifuwu/client |
|
|
182
|
-
| `weifuwu/layout` | **CSS 布局** | 35 个布局原语 +
|
|
182
|
+
| `weifuwu/layout` | **CSS 布局** | 35 个布局原语 + 82 个主题 Token(也支持 `weifuwu/layout/style.css`) | — |
|
|
183
183
|
|
|
184
184
|
---
|
|
185
185
|
|
|
@@ -465,7 +465,7 @@ app.get('/assets/*', serveStatic('./assets', {
|
|
|
465
465
|
|
|
466
466
|
## postgres — PostgreSQL 客户端(自研)
|
|
467
467
|
|
|
468
|
-
> **自研 PG v3 协议**(零第三方依赖)——支持 SCRAM-SHA-256
|
|
468
|
+
> **自研 PG v3 协议**(零第三方依赖)——支持 SCRAM-SHA-256 认证、扩展查询(参数化)、类型映射(int8 超范围自动 string 防丢精度)、事务、连接池(acquire 超时防饿死)、schema 写前校验、statement_timeout 慢查询保护。
|
|
469
469
|
|
|
470
470
|
```ts
|
|
471
471
|
import { postgres } from 'weifuwu'
|
|
@@ -534,15 +534,47 @@ await ctx.sql.insert('decks', { title: 'x', status: 'INVALID' }) // → Validati
|
|
|
534
534
|
| `ctx.sql.transaction(fn)` | 事务(回调收到 `{ query }`) |
|
|
535
535
|
| `ctx.sql.register(table, schema)` | 注册表结构(写前校验) |
|
|
536
536
|
| `ctx.sql.insert(table, row)` | schema 校验 + 参数化插入 |
|
|
537
|
+
| `ctx.sql\`...\` 内嵌片段` | 条件 SQL 片段(嵌套过滤,参数自动重编号) |
|
|
537
538
|
| `ctx.sql.close()` | 关闭连接池 |
|
|
538
539
|
|
|
540
|
+
### 条件片段(嵌套过滤)
|
|
541
|
+
|
|
542
|
+
```ts
|
|
543
|
+
const status = req.query.status // 可能为空
|
|
544
|
+
const rows = await ctx.sql`
|
|
545
|
+
SELECT * FROM orders WHERE amount > ${100}
|
|
546
|
+
${status ? ctx.sql`AND status = ${status}` : ctx.sql``}
|
|
547
|
+
`
|
|
548
|
+
// 空片段内联为空,参数自动重编号——同一 SQL 无论条件多少都安全参数化
|
|
549
|
+
```
|
|
550
|
+
|
|
539
551
|
### 选项
|
|
540
552
|
|
|
541
553
|
| 选项 | 类型 | 默认值 | 说明 |
|
|
542
554
|
|------|------|--------|------|
|
|
543
|
-
| `
|
|
555
|
+
| `connection` | `string` | `DATABASE_URL` | 连接字符串 |
|
|
556
|
+
| `max`(或 `poolSize`) | `number` | `10` | 连接池大小 |
|
|
544
557
|
| `acquireTimeoutMs` | `number` | `30000` | 池全忙时 acquire 超时(防饿死,0=无限) |
|
|
545
|
-
| `statementTimeoutMs` | `number` | `0` | 语句超时(慢查询保护,0=禁用) |
|
|
558
|
+
| `statementTimeoutMs`(或 `statementTimeout`) | `number` | `0` | 语句超时(慢查询保护,0=禁用) |
|
|
559
|
+
| `onQuery` | `(sql, durationMs, rowCount) => void` | — | 查询观测钩子(慢查询日志/审计) |
|
|
560
|
+
|
|
561
|
+
### 幂等迁移(内置)
|
|
562
|
+
|
|
563
|
+
`postgres()` 返回的中间件自带迁移跟踪(`_weifuwu_migrations` 表),模块启动时检查-执行-记录三步幂等:
|
|
564
|
+
|
|
565
|
+
```ts
|
|
566
|
+
const db = postgres()
|
|
567
|
+
await db.migrate() // ① 建迁移跟踪表(幂等)
|
|
568
|
+
|
|
569
|
+
if (!(await db.isMigrated('users'))) { // ② 检查是否已迁移
|
|
570
|
+
await db.sql.unsafe(`CREATE TABLE users (...)`)
|
|
571
|
+
await db.markMigrated('users') // ③ 记录(幂等,重复调用无害)
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
app.use(db)
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
> 多副本部署时天然安全:`markMigrated` 用 `ON CONFLICT DO NOTHING`,两个实例同时迁移也不会重复执行。
|
|
546
578
|
|
|
547
579
|
### 错误映射(自动)
|
|
548
580
|
|
|
@@ -562,7 +594,7 @@ await ctx.sql.insert('decks', { title: 'x', status: 'INVALID' }) // → Validati
|
|
|
562
594
|
|
|
563
595
|
## redis — Redis 客户端(自研)
|
|
564
596
|
|
|
565
|
-
> **自研 RESP2
|
|
597
|
+
> **自研 RESP2 协议**(零第三方依赖)——连接/重连(断线 pending 拒绝、指数退避)/离线队列/管道/Pub-Sub(订阅断线自动重放)+ 消除 ioredis 高频痛点(TTL 参数顺序、JSON 手动序列化、缓存样板)。
|
|
566
598
|
|
|
567
599
|
```ts
|
|
568
600
|
import { redis } from 'weifuwu'
|
|
@@ -588,6 +620,26 @@ app.get('/llm/:id', async (req, ctx) => {
|
|
|
588
620
|
}, 3600)
|
|
589
621
|
return Response.json(result)
|
|
590
622
|
})
|
|
623
|
+
|
|
624
|
+
// ④ Pub/Sub —— 发布用 ctx.redis,订阅用独立连接(回调式,断线自动重连恢复订阅)
|
|
625
|
+
app.post('/events', async (req, ctx) => {
|
|
626
|
+
await ctx.redis.publish('events', JSON.stringify({ type: 'deck.created' }))
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
const sub = ctx.redis.createSubscriber()
|
|
630
|
+
await sub.connect()
|
|
631
|
+
await sub.subscribe('events', (channel, message) => {
|
|
632
|
+
// 收到实时消息
|
|
633
|
+
})
|
|
634
|
+
await sub.psubscribe('jobs:*', (channel, message) => {
|
|
635
|
+
// 模式匹配订阅
|
|
636
|
+
})
|
|
637
|
+
|
|
638
|
+
// ⑤ 任意命令透传 + keyPrefix 隔离
|
|
639
|
+
await ctx.redis.command('LRANGE', 'list', '0', '-1')
|
|
640
|
+
|
|
641
|
+
app.use(redis({ keyPrefix: 'api:' })) // 之后所有 key 自动加前缀
|
|
642
|
+
await ctx.redis.set('user', 1) // 实际写入 'api:user'
|
|
591
643
|
```
|
|
592
644
|
|
|
593
645
|
### 方法面
|
|
@@ -939,6 +991,35 @@ const Badge: Component = () =>
|
|
|
939
991
|
(props) => h('span', { class: `badge-${props.variant}` }, props.children)
|
|
940
992
|
```
|
|
941
993
|
|
|
994
|
+
### 类型流(props 泛型 + ctx 注入)
|
|
995
|
+
|
|
996
|
+
```tsx
|
|
997
|
+
import type { Component } from 'weifuwu/client'
|
|
998
|
+
import type { ApiInjected, RouteInjected } from 'weifuwu/client'
|
|
999
|
+
|
|
1000
|
+
// ① props 泛型:JSX 使用时自动类型检查(传错类型编译期报错)
|
|
1001
|
+
interface DeckCardProps { title: string; pages: number }
|
|
1002
|
+
const DeckCard: Component<DeckCardProps> = (_init, ctx) =>
|
|
1003
|
+
(props) => <div>{props.title} / {props.pages} 页</div>
|
|
1004
|
+
// <DeckCard title="x" pages={8} /> ✓
|
|
1005
|
+
// <DeckCard title="x" pages="8" /> ✗ 编译期报错
|
|
1006
|
+
|
|
1007
|
+
// ② ctx 注入声明:use(api()).use(router()) 后组件声明依赖,ctx 直接访问
|
|
1008
|
+
const Home: Component<{}, ApiInjected & RouteInjected> = (_init, ctx) => {
|
|
1009
|
+
ctx.api.get('/users') // ✓ 有类型
|
|
1010
|
+
ctx.app.navigate('/x') // ✓ 有类型
|
|
1011
|
+
return () => <h1>Home</h1>
|
|
1012
|
+
}
|
|
1013
|
+
// 未声明的注入字段编译期报错——注入从"文档约定"变成"类型保证"
|
|
1014
|
+
|
|
1015
|
+
createApp()
|
|
1016
|
+
.use(api()) // 注入 ctx.api
|
|
1017
|
+
.use(router({ routes })) // 注入 ctx.route / ctx.app
|
|
1018
|
+
.mount('#root', Home) // mount 时类型累积完整
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
> 各中间件的注入接口:`api()` → `ApiInjected`、`auth()` → `AuthInjected`、`ws()` → `WsInjected`、`i18n()` → `I18nInjected`、`router()` → `RouteInjected`(均可从 `weifuwu/client` 导入)。
|
|
1022
|
+
|
|
942
1023
|
| 规则 | 说明 |
|
|
943
1024
|
|------|------|
|
|
944
1025
|
| 组件签名 | `(initProps: P, ctx: WfuiContext) => (props: P) => VNode \| null` |
|
|
@@ -967,6 +1048,20 @@ h('div', { class: 'x' }, child1, child2)
|
|
|
967
1048
|
| `h(type, props, ...children)` | hyperscript |
|
|
968
1049
|
| `jsx` / `jsxs` / `jsxDEV` | JSX 编译目标 |
|
|
969
1050
|
| `Fragment` | 片段 |
|
|
1051
|
+
| `Portal` / `createPortal(children, portalKey?)` | 渲染到 `document.body#__wf_portal` 独立容器(弹层/对话框,脱离父级 overflow 裁剪) |
|
|
1052
|
+
|
|
1053
|
+
```tsx
|
|
1054
|
+
import { createPortal } from 'weifuwu/client'
|
|
1055
|
+
|
|
1056
|
+
// 内容渲染到 body 下的独立容器(不在父组件的 DOM 树内)
|
|
1057
|
+
const Tooltip = (_init, ctx) =>
|
|
1058
|
+
(props) => createPortal(
|
|
1059
|
+
<div class="tooltip">{props.text}</div>
|
|
1060
|
+
)
|
|
1061
|
+
|
|
1062
|
+
// 配合 ctx.ui.selfId('name') 可从任何地方精准刷新 portal 内容
|
|
1063
|
+
ctx.ui.render(['name'])
|
|
1064
|
+
```
|
|
970
1065
|
|
|
971
1066
|
---
|
|
972
1067
|
|
|
@@ -2061,7 +2156,7 @@ props 变化 ──────────────────────
|
|
|
2061
2156
|
|
|
2062
2157
|
# 布局系统 (`weifuwu/layout`)
|
|
2063
2158
|
|
|
2064
|
-
纯 CSS 布局原语 +
|
|
2159
|
+
纯 CSS 布局原语 + 82 个主题 Token。不绑定任何 JS 框架。
|
|
2065
2160
|
|
|
2066
2161
|
> **全栈 weifuwu 项目**:`weifuwu/components/style.css` 已包含布局系统,一条 import 就够了,无需单独引用本页。
|
|
2067
2162
|
> 本页仅适用于**非 weifuwu 项目**或**只需 CSS 布局**的场景。
|
|
@@ -2121,7 +2216,7 @@ app.get('/layout.css', (req, ctx) => ctx.ui.css('weifuwu/layout'))
|
|
|
2121
2216
|
| | `wf-inline-block` | display: inline-block |
|
|
2122
2217
|
| | `wf-contents` | display: contents |
|
|
2123
2218
|
|
|
2124
|
-
##
|
|
2219
|
+
## 82 个主题 Token
|
|
2125
2220
|
|
|
2126
2221
|
```css
|
|
2127
2222
|
/* 品牌色 */
|
package/dist/client/app.d.ts
CHANGED
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
* 并设置 childCtx.ui._selfId = 组件 ID
|
|
15
15
|
* render() 无参时从 this._selfId 取当前组件 ID
|
|
16
16
|
*/
|
|
17
|
-
import type {
|
|
17
|
+
import type { AppMiddleware } from './types.ts';
|
|
18
18
|
import type { Component } from './vnode.ts';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
use(mw: AppMiddleware):
|
|
22
|
-
mount(rootSelector: string,
|
|
23
|
-
|
|
24
|
-
}
|
|
19
|
+
/** 应用句柄:use() 链式累积中间件注入的 ctx 类型,mount() 时组件拿到完整注入 */
|
|
20
|
+
export interface App<C extends object = {}> {
|
|
21
|
+
use<I extends object, O extends object>(mw: AppMiddleware<I, O>): App<C & O>;
|
|
22
|
+
mount(rootSelector: string, root: Component<any, C>): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare function createApp<C extends object = {}>(): App<C>;
|
package/dist/client/i18n.d.ts
CHANGED
|
@@ -24,4 +24,8 @@ export interface I18nState {
|
|
|
24
24
|
setLocale: (lang: string) => void;
|
|
25
25
|
components: Record<string, Record<string, string>>;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
/** i18n 中间件注入到 ctx 的字段 */
|
|
28
|
+
export interface I18nInjected {
|
|
29
|
+
i18n: I18nState;
|
|
30
|
+
}
|
|
31
|
+
export declare function i18n(opts?: I18nOptions): AppMiddleware<{}, I18nInjected>;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -18,19 +18,22 @@
|
|
|
18
18
|
export { h, jsx, jsxs, jsxDEV, Fragment, Portal, createPortal } from './vnode.ts';
|
|
19
19
|
export type { VNode, VNodeType, Component } from './vnode.ts';
|
|
20
20
|
export { createApp } from './app.ts';
|
|
21
|
+
export type { App } from './app.ts';
|
|
21
22
|
export { router, RouteView } from './router.ts';
|
|
23
|
+
export type { RouteInjected } from './router.ts';
|
|
22
24
|
export { ws } from './middleware/ws.ts';
|
|
25
|
+
export type { WsClient, WsInjected } from './middleware/ws.ts';
|
|
23
26
|
export { api } from './middleware/api.ts';
|
|
24
27
|
export { auth } from './middleware/auth.ts';
|
|
25
|
-
export type { ApiClient, ApiOptions, ApiRequestOptions } from './middleware/api.ts';
|
|
28
|
+
export type { ApiClient, ApiOptions, ApiRequestOptions, ApiInjected } from './middleware/api.ts';
|
|
26
29
|
export { ApiError } from './middleware/api.ts';
|
|
27
|
-
export type { AuthClient, AuthOptions } from './middleware/auth.ts';
|
|
30
|
+
export type { AuthClient, AuthOptions, AuthInjected } from './middleware/auth.ts';
|
|
28
31
|
export { extendCtx } from './types.ts';
|
|
29
32
|
export type { WfuiContext, AppMiddleware, RouteDef } from './types.ts';
|
|
30
33
|
export { ErrorBoundary } from './error-boundary.ts';
|
|
31
34
|
export type { ErrorBoundaryProps } from './error-boundary.ts';
|
|
32
35
|
export { i18n } from './i18n.ts';
|
|
33
|
-
export type { I18nOptions, I18nState } from './i18n.ts';
|
|
36
|
+
export type { I18nOptions, I18nState, I18nInjected } from './i18n.ts';
|
|
34
37
|
export { lockScroll, unlockScroll } from './scroll-lock.ts';
|
|
35
38
|
export { trapFocus } from './focus-trap.ts';
|
|
36
39
|
export { computeFixedPos } from './popup.ts';
|
|
@@ -61,7 +61,11 @@ export interface ApiRequestOptions {
|
|
|
61
61
|
* await ctx.api.delete('/users/1')
|
|
62
62
|
* ```
|
|
63
63
|
*/
|
|
64
|
-
|
|
64
|
+
/** api 中间件注入到 ctx 的字段 */
|
|
65
|
+
export interface ApiInjected {
|
|
66
|
+
api: ApiClient;
|
|
67
|
+
}
|
|
68
|
+
export declare function api(options?: ApiOptions): AppMiddleware<{}, ApiInjected>;
|
|
65
69
|
/**
|
|
66
70
|
* API 错误 — 包含 HTTP 状态码和响应文本。
|
|
67
71
|
*
|
|
@@ -21,4 +21,8 @@ export interface AuthClient {
|
|
|
21
21
|
setUser: (user: any) => void;
|
|
22
22
|
refresh: () => Promise<boolean>;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
/** auth 中间件注入到 ctx 的字段 */
|
|
25
|
+
export interface AuthInjected {
|
|
26
|
+
auth: AuthClient;
|
|
27
|
+
}
|
|
28
|
+
export declare function auth(options?: AuthOptions): AppMiddleware<{}, AuthInjected>;
|
|
@@ -12,4 +12,14 @@ export interface WsOptions {
|
|
|
12
12
|
pingInterval?: number;
|
|
13
13
|
pingTimeout?: number;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
/** ws 中间件注入到 ctx 的字段 */
|
|
16
|
+
/** ws 中间件注入的客户端形状(与 WfuiContext.ws 一致) */
|
|
17
|
+
export interface WsClient {
|
|
18
|
+
send: (msg: unknown) => void;
|
|
19
|
+
onMessage: (fn: (data: unknown) => void) => () => void;
|
|
20
|
+
isConnected: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface WsInjected {
|
|
23
|
+
ws: WsClient;
|
|
24
|
+
}
|
|
25
|
+
export declare function ws(options?: WsOptions): AppMiddleware<{}, WsInjected>;
|
package/dist/client/router.d.ts
CHANGED
|
@@ -9,5 +9,18 @@ export interface RouterOptions {
|
|
|
9
9
|
routes: RouteDef[];
|
|
10
10
|
notFound?: (props: any, ctx: WfuiContext) => any;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
/** router 中间件注入到 ctx 的字段 */
|
|
13
|
+
export interface RouteInjected {
|
|
14
|
+
route: {
|
|
15
|
+
path: string;
|
|
16
|
+
params: Record<string, string>;
|
|
17
|
+
query: Record<string, string>;
|
|
18
|
+
title?: string;
|
|
19
|
+
};
|
|
20
|
+
/** 编程式导航 */
|
|
21
|
+
app: {
|
|
22
|
+
navigate: (path: string) => void;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export declare function router(opts: RouterOptions): AppMiddleware<{}, RouteInjected>;
|
|
13
26
|
export declare function RouteView(_props: {}, ctx: WfuiContext): () => any;
|
package/dist/client/types.d.ts
CHANGED
|
@@ -81,7 +81,12 @@ export interface WfuiContext {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
/** 中间件签名 */
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* 前端中间件:输入 ctx 需要 I,输出 ctx 注入 O(链式累积,createApp().use() 类型自动合并)
|
|
86
|
+
* api() → AppMiddleware<{}, ApiInjected> 注入 ctx.api
|
|
87
|
+
* router()→ AppMiddleware<{}, RouteInjected> 注入 ctx.route / ctx.app
|
|
88
|
+
*/
|
|
89
|
+
export type AppMiddleware<I extends object = {}, O extends object = I> = (ctx: WfuiContext & I) => (WfuiContext & O) | Promise<WfuiContext & O>;
|
|
85
90
|
/** 路由定义 */
|
|
86
91
|
export interface RouteDef {
|
|
87
92
|
path: string;
|
package/dist/client/vnode.d.ts
CHANGED
|
@@ -30,7 +30,11 @@ export interface VNode {
|
|
|
30
30
|
/** 组件 mount/render 时的 ctx 版本号(供三态 skip 判定) */
|
|
31
31
|
_ctxVersion?: number;
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* 两阶段组件:外层 = mount(一次),内层 = render(每次 dirty/props 变化)。
|
|
35
|
+
* P = props 类型(JSX 自动推断),C = 组件依赖的 ctx 注入(如 ApiInjected & RouteInjected)
|
|
36
|
+
*/
|
|
37
|
+
export type Component<P = {}, C extends object = {}> = (initProps: P, ctx: WfuiContext & C) => ((props: P) => VNode | null) | null;
|
|
34
38
|
export declare const Fragment: unique symbol;
|
|
35
39
|
/** Portal — 将子 VNode 渲染到 document.body 下的独立容器 */
|
|
36
40
|
export declare const Portal: unique symbol;
|
package/dist/index.js
CHANGED
|
@@ -2175,7 +2175,10 @@ function postgres(options) {
|
|
|
2175
2175
|
user: decodeURIComponent(u.username),
|
|
2176
2176
|
password: decodeURIComponent(u.password),
|
|
2177
2177
|
database: u.pathname.replace(/^\//, ""),
|
|
2178
|
-
poolSize: opts.max ?? 10
|
|
2178
|
+
poolSize: opts.max ?? opts.poolSize ?? 10,
|
|
2179
|
+
acquireTimeoutMs: opts.acquireTimeoutMs,
|
|
2180
|
+
statementTimeoutMs: opts.statementTimeoutMs ?? opts.statementTimeout,
|
|
2181
|
+
onQuery: opts.onQuery
|
|
2179
2182
|
});
|
|
2180
2183
|
const sql = makeSql(pool);
|
|
2181
2184
|
const mw = ((req, ctx, next) => {
|
package/dist/postgres/types.d.ts
CHANGED
|
@@ -24,18 +24,26 @@ export interface PostgresInjected {
|
|
|
24
24
|
sql: SqlClient;
|
|
25
25
|
}
|
|
26
26
|
export interface PostgresOptions {
|
|
27
|
+
/** 连接字符串(默认 DATABASE_URL) */
|
|
27
28
|
connection?: string;
|
|
28
|
-
signal?: AbortSignal;
|
|
29
|
-
closeTimeout?: number;
|
|
30
29
|
/** 池大小(连接数)。默认 10。 */
|
|
31
30
|
max?: number;
|
|
31
|
+
/** 池全忙时 acquire 超时 ms(防饿死)。默认 30_000。0 = 无限。 */
|
|
32
|
+
acquireTimeoutMs?: number;
|
|
33
|
+
/** 语句超时 ms(慢查询保护,会话级 SET statement_timeout)。默认 0 = 禁用。 */
|
|
34
|
+
statementTimeoutMs?: number;
|
|
35
|
+
/** 查询观测钩子(慢查询日志/审计) */
|
|
36
|
+
onQuery?: (query: string, durationMs: number, rowCount: number) => void;
|
|
37
|
+
/** postgres.js 兼容名(= max) */
|
|
38
|
+
poolSize?: number;
|
|
39
|
+
/** postgres.js 兼容名(= statementTimeoutMs) */
|
|
40
|
+
statementTimeout?: number;
|
|
41
|
+
/** 连接超时 ms。默认 10_000。 */
|
|
42
|
+
connect_timeout?: number;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
closeTimeout?: number;
|
|
32
45
|
ssl?: boolean | Record<string, unknown>;
|
|
33
46
|
idle_timeout?: number;
|
|
34
|
-
connect_timeout?: number;
|
|
35
|
-
/** 兼容保留(自研客户端暂以连接池替代 statement_timeout 注入) */
|
|
36
|
-
statementTimeout?: number;
|
|
37
|
-
/** Called after every query completes. */
|
|
38
|
-
onQuery?: (query: string, durationMs: number, rowCount: number) => void;
|
|
39
47
|
}
|
|
40
48
|
export interface PostgresClient extends Middleware<Context, Context & PostgresInjected>, Closeable {
|
|
41
49
|
sql: SqlClient;
|