@h-ai/reldb 0.1.0-alpha.65 → 0.1.0-alpha.67

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.en.md CHANGED
@@ -4,21 +4,27 @@
4
4
 
5
5
  [Framework home](../../README.en.md) · Related modules: [@h-ai/core](../core/README.en.md)
6
6
 
7
+ ## Introduction
8
+
7
9
  A relational database module with a unified `reldb` object for SQLite, PostgreSQL, and MySQL.
8
10
 
9
- ## Supported databases
11
+ ## Core features
12
+
13
+ - Connect to SQLite, PostgreSQL and MySQL through one API.
14
+ - Run parameterized SQL, manage tables/indexes and read paginated results.
15
+ - Organize application reads and writes with transactions, CRUD and repositories.
10
16
 
11
- - SQLite
12
- - PostgreSQL
13
- - MySQL
17
+ ## Getting started
14
18
 
15
- ## Quick start
19
+ ### Quick start
16
20
 
17
21
  ```ts
18
22
  import { HaiReldbError, reldb } from '@h-ai/reldb'
19
23
 
20
24
  // 初始化
21
- await reldb.init({ type: 'sqlite', database: ':memory:' })
25
+ const initialized = await reldb.init({ type: 'sqlite', database: ':memory:' })
26
+ if (!initialized.success)
27
+ throw new Error(initialized.error.message)
22
28
 
23
29
  // DDL
24
30
  await reldb.ddl.createTable('users', {
@@ -55,7 +61,7 @@ await reldb.close()
55
61
 
56
62
  `reldb.config` returns a **redacted configuration snapshot**. Database `password` and credentials embedded in URLs are hidden automatically. Use it to inspect state, not to replay original connection details.
57
63
 
58
- ## Configuration
64
+ ### Configuration
59
65
 
60
66
  Use either a connection string (`url`) or separate fields (`host/port/database/user/password`).
61
67
 
@@ -78,7 +84,7 @@ await reldb.init({
78
84
  })
79
85
  ```
80
86
 
81
- ### SQLite execution (asynchronous worker)
87
+ #### SQLite execution (asynchronous worker)
82
88
 
83
89
  better-sqlite3 is synchronous, so queries block Node's main event loop. WAL improves database lock concurrency but cannot remove this blocking. To offload it, opt in to a dedicated SQLite worker thread (single connection; defaults to `sync`):
84
90
 
@@ -96,7 +102,7 @@ await reldb.init({
96
102
 
97
103
  In worker mode, queries, writes, and transactions run serially on the worker thread. Public APIs and return values remain identical to synchronous mode.
98
104
 
99
- ### Operation logging
105
+ #### Operation logging
100
106
 
101
107
  Enable SQL operation logs with `operationLog` in the database configuration. Logs are emitted at the DML layer of reldb provider-base, without duplicate wrappers in `reldb-main.ts` or raw providers.
102
108
 
@@ -127,11 +133,11 @@ await reldb.init({
127
133
  })
128
134
  ```
129
135
 
130
- ## Transactions
136
+ ### Transactions
131
137
 
132
138
  Three approaches:
133
139
 
134
- ### wrap (automatic commit/rollback)
140
+ #### wrap (automatic commit/rollback)
135
141
 
136
142
  ```ts
137
143
  const result = await reldb.tx.wrap(async (tx) => {
@@ -142,7 +148,7 @@ const result = await reldb.tx.wrap(async (tx) => {
142
148
  // 回调正常返回 → 自动提交;抛异常 → 自动回滚
143
149
  ```
144
150
 
145
- ### begin + commit (explicit commit)
151
+ #### begin + commit (explicit commit)
146
152
 
147
153
  ```ts
148
154
  const txResult = await reldb.tx.begin()
@@ -154,7 +160,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户2'])
154
160
  await tx.commit()
155
161
  ```
156
162
 
157
- ### begin + rollback (explicit rollback)
163
+ #### begin + rollback (explicit rollback)
158
164
 
159
165
  ```ts
160
166
  const txResult = await reldb.tx.begin()
@@ -166,7 +172,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户1'])
166
172
  await tx.rollback()
167
173
  ```
168
174
 
169
- ### batch / queryPage inside transactions
175
+ #### batch / queryPage inside transactions
170
176
 
171
177
  ```ts
172
178
  await reldb.tx.wrap(async (tx) => {
@@ -182,7 +188,7 @@ await reldb.tx.wrap(async (tx) => {
182
188
  })
183
189
  ```
184
190
 
185
- ## Crud
191
+ ### Crud
186
192
 
187
193
  Create a single-table CRUD repository with `reldb.crud.table()`, without writing SQL:
188
194
 
@@ -197,7 +203,7 @@ const userCrud = reldb.crud.table<{ id: number, name: string, email: string }>({
197
203
  })
198
204
  ```
199
205
 
200
- ### create / createMany
206
+ #### create / createMany
201
207
 
202
208
  ```ts
203
209
  // 单条插入
@@ -211,7 +217,7 @@ await userCrud.createMany([
211
217
  ])
212
218
  ```
213
219
 
214
- ### createOrUpdate
220
+ #### createOrUpdate
215
221
 
216
222
  Update when the primary key exists; otherwise create (upsert):
217
223
 
@@ -230,7 +236,7 @@ await userCrud.createOrUpdate({ id: 1, name: '张三', email: 'test@example.com'
230
236
 
231
237
  `BaseReldbCrudRepository` obtains `dbType` automatically; no manual argument is needed.
232
238
 
233
- ### findById / getById / findAll / findPage
239
+ #### findById / getById / findAll / findPage
234
240
 
235
241
  ```ts
236
242
  // 主键查找(不存在时返回 null)
@@ -260,14 +266,14 @@ const page = await userCrud.findPage({
260
266
  // page.data → { items: [...], total: 100, page: 1, pageSize: 20 }
261
267
  ```
262
268
 
263
- ### updateById / deleteById
269
+ #### updateById / deleteById
264
270
 
265
271
  ```ts
266
272
  await userCrud.updateById(1, { name: '李四' })
267
273
  await userCrud.deleteById(1)
268
274
  ```
269
275
 
270
- ### count / exists / existsById
276
+ #### count / exists / existsById
271
277
 
272
278
  ```ts
273
279
  const total = await userCrud.count({ where: 'name LIKE ?', params: ['%张%'] })
@@ -280,7 +286,7 @@ const found = await userCrud.existsById(1)
280
286
  // found.data → true
281
287
  ```
282
288
 
283
- ### Crud inside transactions
289
+ #### Crud inside transactions
284
290
 
285
291
  All methods accept `tx` and automatically route operations to that transaction context:
286
292
 
@@ -292,7 +298,7 @@ await reldb.tx.wrap(async (tx) => {
292
298
  })
293
299
  ```
294
300
 
295
- ## BaseReldbCrudRepository
301
+ ### BaseReldbCrudRepository
296
302
 
297
303
  Business repositories extend `BaseReldbCrudRepository` and define field mappings with `fields` for automatic table creation and type conversion:
298
304
 
@@ -359,7 +365,7 @@ if (txResult.success) {
359
365
  }
360
366
  ```
361
367
 
362
- ## JSON path operations
368
+ ### JSON path operations
363
369
 
364
370
  Use `reldb.json` to build SQL expressions for consistent JSON path operations across databases.
365
371
 
@@ -375,7 +381,7 @@ Paths follow SQL/JSON Path (`$.key` / `$.key.subkey` / `$[0]`); each backend map
375
381
 
376
382
  All methods return `{ sql, params }` fragments that can be embedded in `reldb.sql.query` / `reldb.sql.execute`.
377
383
 
378
- ### extract — read a JSON field value
384
+ #### extract — read a JSON field value
379
385
 
380
386
  ```ts
381
387
  // 用于 WHERE 条件
@@ -393,7 +399,7 @@ const result = await reldb.sql.query(
393
399
  )
394
400
  ```
395
401
 
396
- ### set — set a JSON path (create or replace)
402
+ #### set — set a JSON path (create or replace)
397
403
 
398
404
  ```ts
399
405
  const { sql, params } = reldb.json.set('settings', '$.theme', 'dark')
@@ -403,7 +409,7 @@ await reldb.sql.execute(
403
409
  )
404
410
  ```
405
411
 
406
- ### insert — insert at a JSON path (only when absent)
412
+ #### insert — insert at a JSON path (only when absent)
407
413
 
408
414
  ```ts
409
415
  const { sql, params } = reldb.json.insert('data', '$.firstSeen', new Date().toISOString())
@@ -413,7 +419,7 @@ await reldb.sql.execute(
413
419
  )
414
420
  ```
415
421
 
416
- ### remove — remove a JSON path
422
+ #### remove — remove a JSON path
417
423
 
418
424
  ```ts
419
425
  const { sql, params } = reldb.json.remove('settings', '$.deprecated')
@@ -423,7 +429,7 @@ await reldb.sql.execute(
423
429
  )
424
430
  ```
425
431
 
426
- ### merge — merge JSON objects (RFC 7396 Merge Patch)
432
+ #### merge — merge JSON objects (RFC 7396 Merge Patch)
427
433
 
428
434
  ```ts
429
435
  // 覆盖已有键、保留未提及键、将 null 键删除
@@ -437,7 +443,7 @@ await reldb.sql.execute(
437
443
  )
438
444
  ```
439
445
 
440
- ### Complete example
446
+ #### Complete example
441
447
 
442
448
  ```ts
443
449
  // 建表(含 JSON 列)
@@ -472,7 +478,7 @@ const { sql: rmSql, params: rmParams } = reldb.json.remove('meta', '$.reviewer')
472
478
  await reldb.sql.execute(`UPDATE products SET meta = ${rmSql} WHERE id = ?`, [...rmParams, 1])
473
479
  ```
474
480
 
475
- ## Error handling
481
+ ### Error handling
476
482
 
477
483
  All operations return `HaiResult<T>`; check `result.success` for success or failure.
478
484
 
@@ -507,7 +513,7 @@ Common error codes:
507
513
  | `HaiReldbError.DDL_FAILED` | `hai:reldb:020` | DDL operation failed |
508
514
  | `HaiReldbError.CONFIG_ERROR` | `hai:reldb:013` | Invalid configuration |
509
515
 
510
- ## Tests
516
+ ## Development and testing
511
517
 
512
518
  ```bash
513
519
  pnpm --filter @h-ai/reldb test
package/README.ja.md CHANGED
@@ -4,21 +4,27 @@
4
4
 
5
5
  [フレームワークのホーム](../../README.ja.md) · 関連モジュール:[@h-ai/core](../core/README.ja.md)
6
6
 
7
+ ## 概要
8
+
7
9
  共通の `reldb` オブジェクトで SQLite、PostgreSQL、MySQL を操作するリレーショナルデータベースモジュールです。
8
10
 
9
- ## 対応データベース
11
+ ## 主な機能
12
+
13
+ - 共通 API で SQLite・PostgreSQL・MySQL に接続。
14
+ - パラメーター付き SQL、テーブル・索引管理、ページ取得。
15
+ - トランザクション、CRUD、Repository による業務の読み書き。
10
16
 
11
- - SQLite
12
- - PostgreSQL
13
- - MySQL
17
+ ## 使い始める
14
18
 
15
- ## クイックスタート
19
+ ### クイックスタート
16
20
 
17
21
  ```ts
18
22
  import { HaiReldbError, reldb } from '@h-ai/reldb'
19
23
 
20
24
  // 初始化
21
- await reldb.init({ type: 'sqlite', database: ':memory:' })
25
+ const initialized = await reldb.init({ type: 'sqlite', database: ':memory:' })
26
+ if (!initialized.success)
27
+ throw new Error(initialized.error.message)
22
28
 
23
29
  // DDL
24
30
  await reldb.ddl.createTable('users', {
@@ -55,7 +61,7 @@ await reldb.close()
55
61
 
56
62
  `reldb.config` は**機密情報をマスクした設定スナップショット**を返します。DB の `password` と URL 内の認証情報は自動的に非表示になります。状態確認用であり、元の接続情報の再利用には使わないでください。
57
63
 
58
- ## 設定
64
+ ### 設定
59
65
 
60
66
  接続文字列(`url`)または個別フィールド(`host/port/database/user/password`)を指定できます。
61
67
 
@@ -78,7 +84,7 @@ await reldb.init({
78
84
  })
79
85
  ```
80
86
 
81
- ### SQLite の実行方式(非同期 worker)
87
+ #### SQLite の実行方式(非同期 worker)
82
88
 
83
89
  better-sqlite3 は同期ドライバーなので、クエリは Node のメインイベントループをブロックします。WAL は DB ロックの並行性を改善しますが、同期呼び出しによるブロックは解消しません。専用 worker スレッドで SQLite を実行して処理を移せます(単一接続、任意設定、既定は `sync`):
84
90
 
@@ -96,7 +102,7 @@ await reldb.init({
96
102
 
97
103
  worker モードではクエリ、書き込み、トランザクションを worker スレッドで順番に実行します。公開 API と戻り値は同期モードと同じです。
98
104
 
99
- ### 操作ログ
105
+ #### 操作ログ
100
106
 
101
107
  DB 設定の `operationLog` で SQL 操作ログを有効にできます。ログは reldb provider-base の DML 層で出力され、`reldb-main.ts` や各 raw provider で重複してラップしません。
102
108
 
@@ -127,11 +133,11 @@ await reldb.init({
127
133
  })
128
134
  ```
129
135
 
130
- ## トランザクション
136
+ ### トランザクション
131
137
 
132
138
  3 種類の使用方法:
133
139
 
134
- ### wrap(自動コミット/ロールバック)
140
+ #### wrap(自動コミット/ロールバック)
135
141
 
136
142
  ```ts
137
143
  const result = await reldb.tx.wrap(async (tx) => {
@@ -142,7 +148,7 @@ const result = await reldb.tx.wrap(async (tx) => {
142
148
  // 回调正常返回 → 自动提交;抛异常 → 自动回滚
143
149
  ```
144
150
 
145
- ### begin + commit(手動コミット)
151
+ #### begin + commit(手動コミット)
146
152
 
147
153
  ```ts
148
154
  const txResult = await reldb.tx.begin()
@@ -154,7 +160,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户2'])
154
160
  await tx.commit()
155
161
  ```
156
162
 
157
- ### begin + rollback(手動ロールバック)
163
+ #### begin + rollback(手動ロールバック)
158
164
 
159
165
  ```ts
160
166
  const txResult = await reldb.tx.begin()
@@ -166,7 +172,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户1'])
166
172
  await tx.rollback()
167
173
  ```
168
174
 
169
- ### トランザクション内での batch / queryPage
175
+ #### トランザクション内での batch / queryPage
170
176
 
171
177
  ```ts
172
178
  await reldb.tx.wrap(async (tx) => {
@@ -182,7 +188,7 @@ await reldb.tx.wrap(async (tx) => {
182
188
  })
183
189
  ```
184
190
 
185
- ## Crud
191
+ ### Crud
186
192
 
187
193
  `reldb.crud.table()` で単一テーブルの CRUD リポジトリーを作成できます。SQL の記述は不要です:
188
194
 
@@ -197,7 +203,7 @@ const userCrud = reldb.crud.table<{ id: number, name: string, email: string }>({
197
203
  })
198
204
  ```
199
205
 
200
- ### create / createMany
206
+ #### create / createMany
201
207
 
202
208
  ```ts
203
209
  // 单条插入
@@ -211,7 +217,7 @@ await userCrud.createMany([
211
217
  ])
212
218
  ```
213
219
 
214
- ### createOrUpdate
220
+ #### createOrUpdate
215
221
 
216
222
  主キーが存在すれば更新し、存在しなければ作成します(upsert):
217
223
 
@@ -230,7 +236,7 @@ await userCrud.createOrUpdate({ id: 1, name: '张三', email: 'test@example.com'
230
236
 
231
237
  `BaseReldbCrudRepository` は `dbType` を自動取得するため、手動指定は不要です。
232
238
 
233
- ### findById / getById / findAll / findPage
239
+ #### findById / getById / findAll / findPage
234
240
 
235
241
  ```ts
236
242
  // 主键查找(不存在时返回 null)
@@ -260,14 +266,14 @@ const page = await userCrud.findPage({
260
266
  // page.data → { items: [...], total: 100, page: 1, pageSize: 20 }
261
267
  ```
262
268
 
263
- ### updateById / deleteById
269
+ #### updateById / deleteById
264
270
 
265
271
  ```ts
266
272
  await userCrud.updateById(1, { name: '李四' })
267
273
  await userCrud.deleteById(1)
268
274
  ```
269
275
 
270
- ### count / exists / existsById
276
+ #### count / exists / existsById
271
277
 
272
278
  ```ts
273
279
  const total = await userCrud.count({ where: 'name LIKE ?', params: ['%张%'] })
@@ -280,7 +286,7 @@ const found = await userCrud.existsById(1)
280
286
  // found.data → true
281
287
  ```
282
288
 
283
- ### トランザクション内での Crud
289
+ #### トランザクション内での Crud
284
290
 
285
291
  すべてのメソッドに `tx` を渡すことができ、対応するトランザクションのコンテキストへ自動的に切り替わります:
286
292
 
@@ -292,7 +298,7 @@ await reldb.tx.wrap(async (tx) => {
292
298
  })
293
299
  ```
294
300
 
295
- ## BaseReldbCrudRepository
301
+ ### BaseReldbCrudRepository
296
302
 
297
303
  業務リポジトリーは `BaseReldbCrudRepository` を継承し、`fields` でフィールドの対応を定義します。テーブル作成と型変換は自動です:
298
304
 
@@ -359,7 +365,7 @@ if (txResult.success) {
359
365
  }
360
366
  ```
361
367
 
362
- ## JSON パス操作
368
+ ### JSON パス操作
363
369
 
364
370
  `reldb.json` で、複数のデータベースに共通する JSON パス操作の SQL 式を作成します。
365
371
 
@@ -375,7 +381,7 @@ if (txResult.success) {
375
381
 
376
382
  すべてのメソッドは `{ sql, params }` の断片を返し、`reldb.sql.query` / `reldb.sql.execute` に直接組み込めます。
377
383
 
378
- ### extract — JSON フィールド値の取得
384
+ #### extract — JSON フィールド値の取得
379
385
 
380
386
  ```ts
381
387
  // 用于 WHERE 条件
@@ -393,7 +399,7 @@ const result = await reldb.sql.query(
393
399
  )
394
400
  ```
395
401
 
396
- ### set — JSON パスの設定(作成または置換)
402
+ #### set — JSON パスの設定(作成または置換)
397
403
 
398
404
  ```ts
399
405
  const { sql, params } = reldb.json.set('settings', '$.theme', 'dark')
@@ -403,7 +409,7 @@ await reldb.sql.execute(
403
409
  )
404
410
  ```
405
411
 
406
- ### insert — JSON パスへの挿入(未存在の場合のみ)
412
+ #### insert — JSON パスへの挿入(未存在の場合のみ)
407
413
 
408
414
  ```ts
409
415
  const { sql, params } = reldb.json.insert('data', '$.firstSeen', new Date().toISOString())
@@ -413,7 +419,7 @@ await reldb.sql.execute(
413
419
  )
414
420
  ```
415
421
 
416
- ### remove — JSON パスの削除
422
+ #### remove — JSON パスの削除
417
423
 
418
424
  ```ts
419
425
  const { sql, params } = reldb.json.remove('settings', '$.deprecated')
@@ -423,7 +429,7 @@ await reldb.sql.execute(
423
429
  )
424
430
  ```
425
431
 
426
- ### merge — JSON オブジェクトのマージ(RFC 7396 Merge Patch)
432
+ #### merge — JSON オブジェクトのマージ(RFC 7396 Merge Patch)
427
433
 
428
434
  ```ts
429
435
  // 覆盖已有键、保留未提及键、将 null 键删除
@@ -437,7 +443,7 @@ await reldb.sql.execute(
437
443
  )
438
444
  ```
439
445
 
440
- ### 完全な使用例
446
+ #### 完全な使用例
441
447
 
442
448
  ```ts
443
449
  // 建表(含 JSON 列)
@@ -472,7 +478,7 @@ const { sql: rmSql, params: rmParams } = reldb.json.remove('meta', '$.reviewer')
472
478
  await reldb.sql.execute(`UPDATE products SET meta = ${rmSql} WHERE id = ?`, [...rmParams, 1])
473
479
  ```
474
480
 
475
- ## エラー処理
481
+ ### エラー処理
476
482
 
477
483
  すべての操作は `HaiResult<T>` を返し、`result.success` で成功・失敗を判定します。
478
484
 
@@ -507,7 +513,7 @@ if (!result.success) {
507
513
  | `HaiReldbError.DDL_FAILED` | `hai:reldb:020` | DDL 操作に失敗 |
508
514
  | `HaiReldbError.CONFIG_ERROR` | `hai:reldb:013` | 設定エラー |
509
515
 
510
- ## テスト
516
+ ## 開発とテスト
511
517
 
512
518
  ```bash
513
519
  pnpm --filter @h-ai/reldb test
@@ -515,6 +521,6 @@ pnpm --filter @h-ai/reldb test
515
521
 
516
522
  > MySQL/PostgreSQL のテストには Docker が必要です。
517
523
 
518
- ## License
524
+ ## ライセンス
519
525
 
520
526
  Apache-2.0
package/README.md CHANGED
@@ -4,21 +4,27 @@
4
4
 
5
5
  [框架首页](../../README.md) · 相关模块:[@h-ai/core](../core/README.md)
6
6
 
7
+ ## 简介
8
+
7
9
  关系型数据库访问模块,通过统一的 `reldb` 对象访问 SQLite、PostgreSQL、MySQL。
8
10
 
9
- ## 支持的数据库
11
+ ## 核心功能清单
12
+
13
+ - 用同一套 API 连接 SQLite、PostgreSQL 和 MySQL。
14
+ - 执行参数化 SQL,创建表和索引,读取分页结果。
15
+ - 使用事务、CRUD 与 Repository 组织业务读写。
10
16
 
11
- - SQLite
12
- - PostgreSQL
13
- - MySQL
17
+ ## 使用入门
14
18
 
15
- ## 快速开始
19
+ ### 快速开始
16
20
 
17
21
  ```ts
18
22
  import { HaiReldbError, reldb } from '@h-ai/reldb'
19
23
 
20
24
  // 初始化
21
- await reldb.init({ type: 'sqlite', database: ':memory:' })
25
+ const initialized = await reldb.init({ type: 'sqlite', database: ':memory:' })
26
+ if (!initialized.success)
27
+ throw new Error(initialized.error.message)
22
28
 
23
29
  // DDL
24
30
  await reldb.ddl.createTable('users', {
@@ -55,7 +61,7 @@ await reldb.close()
55
61
 
56
62
  `reldb.config` 返回的是**脱敏后的配置快照**:数据库 `password` 与 URL 内嵌凭证会自动隐藏,便于排查状态但不应用于回放原始连接信息。
57
63
 
58
- ## 配置
64
+ ### 配置
59
65
 
60
66
  支持连接字符串(`url`)或分字段(`host/port/database/user/password`)。
61
67
 
@@ -78,7 +84,7 @@ await reldb.init({
78
84
  })
79
85
  ```
80
86
 
81
- ### SQLite 执行方式(worker 异步)
87
+ #### SQLite 执行方式(worker 异步)
82
88
 
83
89
  better-sqlite3 是同步驱动,查询会阻塞 Node 主线程事件循环。WAL 只能改善数据库锁并发,无法避免同步调用占用主线程。需要卸载这一阻塞时,可把 SQLite 切到专用 worker 线程执行(单连接,opt-in,默认 `sync`):
84
90
 
@@ -96,7 +102,7 @@ await reldb.init({
96
102
 
97
103
  worker 模式下查询、写入与事务均在 worker 线程串行执行;公共 API 与返回值与同步模式完全一致。
98
104
 
99
- ### 操作日志
105
+ #### 操作日志
100
106
 
101
107
  可在数据库配置中通过 `operationLog` 开启 SQL 操作日志。日志在 reldb provider-base 的 DML 操作层统一输出,不在 `reldb-main.ts` 或各 raw provider 中重复包装。
102
108
 
@@ -127,11 +133,11 @@ await reldb.init({
127
133
  })
128
134
  ```
129
135
 
130
- ## 事务
136
+ ### 事务
131
137
 
132
138
  三种使用方式:
133
139
 
134
- ### wrap(自动提交/回滚)
140
+ #### wrap(自动提交/回滚)
135
141
 
136
142
  ```ts
137
143
  const result = await reldb.tx.wrap(async (tx) => {
@@ -142,7 +148,7 @@ const result = await reldb.tx.wrap(async (tx) => {
142
148
  // 回调正常返回 → 自动提交;抛异常 → 自动回滚
143
149
  ```
144
150
 
145
- ### begin + commit(分步提交)
151
+ #### begin + commit(分步提交)
146
152
 
147
153
  ```ts
148
154
  const txResult = await reldb.tx.begin()
@@ -154,7 +160,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户2'])
154
160
  await tx.commit()
155
161
  ```
156
162
 
157
- ### begin + rollback(分步回滚)
163
+ #### begin + rollback(分步回滚)
158
164
 
159
165
  ```ts
160
166
  const txResult = await reldb.tx.begin()
@@ -166,7 +172,7 @@ await tx.execute('INSERT INTO users (name) VALUES (?)', ['用户1'])
166
172
  await tx.rollback()
167
173
  ```
168
174
 
169
- ### 事务内使用 batch / queryPage
175
+ #### 事务内使用 batch / queryPage
170
176
 
171
177
  ```ts
172
178
  await reldb.tx.wrap(async (tx) => {
@@ -182,7 +188,7 @@ await reldb.tx.wrap(async (tx) => {
182
188
  })
183
189
  ```
184
190
 
185
- ## Crud
191
+ ### Crud
186
192
 
187
193
  通过 `reldb.crud.table()` 创建单表 CRUD 仓库,免写 SQL:
188
194
 
@@ -197,7 +203,7 @@ const userCrud = reldb.crud.table<{ id: number, name: string, email: string }>({
197
203
  })
198
204
  ```
199
205
 
200
- ### create / createMany
206
+ #### create / createMany
201
207
 
202
208
  ```ts
203
209
  // 单条插入
@@ -211,7 +217,7 @@ await userCrud.createMany([
211
217
  ])
212
218
  ```
213
219
 
214
- ### createOrUpdate
220
+ #### createOrUpdate
215
221
 
216
222
  主键存在时更新,否则创建(upsert):
217
223
 
@@ -230,7 +236,7 @@ await userCrud.createOrUpdate({ id: 1, name: '张三', email: 'test@example.com'
230
236
 
231
237
  `BaseReldbCrudRepository` 自动获取 `dbType`,无需手动传入。
232
238
 
233
- ### findById / getById / findAll / findPage
239
+ #### findById / getById / findAll / findPage
234
240
 
235
241
  ```ts
236
242
  // 主键查找(不存在时返回 null)
@@ -260,14 +266,14 @@ const page = await userCrud.findPage({
260
266
  // page.data → { items: [...], total: 100, page: 1, pageSize: 20 }
261
267
  ```
262
268
 
263
- ### updateById / deleteById
269
+ #### updateById / deleteById
264
270
 
265
271
  ```ts
266
272
  await userCrud.updateById(1, { name: '李四' })
267
273
  await userCrud.deleteById(1)
268
274
  ```
269
275
 
270
- ### count / exists / existsById
276
+ #### count / exists / existsById
271
277
 
272
278
  ```ts
273
279
  const total = await userCrud.count({ where: 'name LIKE ?', params: ['%张%'] })
@@ -280,7 +286,7 @@ const found = await userCrud.existsById(1)
280
286
  // found.data → true
281
287
  ```
282
288
 
283
- ### 事务中使用 Crud
289
+ #### 事务中使用 Crud
284
290
 
285
291
  所有方法均支持传入 `tx` 参数,自动路由到事务上下文:
286
292
 
@@ -292,7 +298,7 @@ await reldb.tx.wrap(async (tx) => {
292
298
  })
293
299
  ```
294
300
 
295
- ## BaseReldbCrudRepository
301
+ ### BaseReldbCrudRepository
296
302
 
297
303
  业务仓库继承 `BaseReldbCrudRepository`,通过 `fields` 定义字段映射,自动建表、类型转换:
298
304
 
@@ -359,7 +365,7 @@ if (txResult.success) {
359
365
  }
360
366
  ```
361
367
 
362
- ## JSON 路径操作
368
+ ### JSON 路径操作
363
369
 
364
370
  通过 `reldb.json` 构建跨数据库统一的 JSON 路径操作 SQL 表达式。
365
371
 
@@ -375,7 +381,7 @@ if (txResult.success) {
375
381
 
376
382
  所有方法返回 `{ sql, params }` 片段,可直接嵌入 `reldb.sql.query` / `reldb.sql.execute`。
377
383
 
378
- ### extract — 提取 JSON 字段值
384
+ #### extract — 提取 JSON 字段值
379
385
 
380
386
  ```ts
381
387
  // 用于 WHERE 条件
@@ -393,7 +399,7 @@ const result = await reldb.sql.query(
393
399
  )
394
400
  ```
395
401
 
396
- ### set — 设置 JSON 字段路径(创建或替换)
402
+ #### set — 设置 JSON 字段路径(创建或替换)
397
403
 
398
404
  ```ts
399
405
  const { sql, params } = reldb.json.set('settings', '$.theme', 'dark')
@@ -403,7 +409,7 @@ await reldb.sql.execute(
403
409
  )
404
410
  ```
405
411
 
406
- ### insert — 插入 JSON 字段路径(仅当路径不存在时)
412
+ #### insert — 插入 JSON 字段路径(仅当路径不存在时)
407
413
 
408
414
  ```ts
409
415
  const { sql, params } = reldb.json.insert('data', '$.firstSeen', new Date().toISOString())
@@ -413,7 +419,7 @@ await reldb.sql.execute(
413
419
  )
414
420
  ```
415
421
 
416
- ### remove — 删除 JSON 字段路径
422
+ #### remove — 删除 JSON 字段路径
417
423
 
418
424
  ```ts
419
425
  const { sql, params } = reldb.json.remove('settings', '$.deprecated')
@@ -423,7 +429,7 @@ await reldb.sql.execute(
423
429
  )
424
430
  ```
425
431
 
426
- ### merge — 合并 JSON 对象(RFC 7396 Merge Patch)
432
+ #### merge — 合并 JSON 对象(RFC 7396 Merge Patch)
427
433
 
428
434
  ```ts
429
435
  // 覆盖已有键、保留未提及键、将 null 键删除
@@ -437,7 +443,7 @@ await reldb.sql.execute(
437
443
  )
438
444
  ```
439
445
 
440
- ### 完整示例
446
+ #### 完整示例
441
447
 
442
448
  ```ts
443
449
  // 建表(含 JSON 列)
@@ -472,7 +478,7 @@ const { sql: rmSql, params: rmParams } = reldb.json.remove('meta', '$.reviewer')
472
478
  await reldb.sql.execute(`UPDATE products SET meta = ${rmSql} WHERE id = ?`, [...rmParams, 1])
473
479
  ```
474
480
 
475
- ## 错误处理
481
+ ### 错误处理
476
482
 
477
483
  所有操作返回 `HaiResult<T>`,通过 `result.success` 判断成功或失败。
478
484
 
@@ -507,7 +513,7 @@ if (!result.success) {
507
513
  | `HaiReldbError.DDL_FAILED` | `hai:reldb:020` | DDL 操作失败 |
508
514
  | `HaiReldbError.CONFIG_ERROR` | `hai:reldb:013` | 配置错误 |
509
515
 
510
- ## 测试
516
+ ## 开发测试
511
517
 
512
518
  ```bash
513
519
  pnpm --filter @h-ai/reldb test
@@ -515,6 +521,6 @@ pnpm --filter @h-ai/reldb test
515
521
 
516
522
  > MySQL/PostgreSQL 测试需要 Docker。
517
523
 
518
- ## License
524
+ ## 许可证
519
525
 
520
526
  Apache-2.0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/reldb",
3
3
  "type": "module",
4
- "version": "0.1.0-alpha.65",
4
+ "version": "0.1.0-alpha.67",
5
5
  "description": "Hai Framework relational database module for SQLite, PostgreSQL, and MySQL.",
6
6
  "license": "Apache-2.0",
7
7
  "exports": {
@@ -23,7 +23,7 @@
23
23
  "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
24
24
  },
25
25
  "dependencies": {
26
- "@h-ai/core": "0.1.0-alpha.65",
26
+ "@h-ai/core": "0.1.0-alpha.67",
27
27
  "better-sqlite3": "^12.11.1",
28
28
  "zod": "^4.6.5"
29
29
  },