@h-ai/reldb 0.1.0-alpha.49 → 0.1.0-alpha.50
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 +18 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +201 -65
- package/dist/index.js.map +1 -1
- package/dist/providers/sqlite/reldb-sqlite-worker.mjs +112 -0
- package/package.json +2 -2
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/reldb — SQLite worker 线程脚本
|
|
3
|
+
*
|
|
4
|
+
* 纯 JavaScript,供 worker_threads 直接加载(源码与打包运行位置均可)。
|
|
5
|
+
* 持有唯一 better-sqlite3 连接,按 FIFO 串行处理主线程消息,把同步查询的阻塞移出主线程事件循环。
|
|
6
|
+
*
|
|
7
|
+
* 消息协议:
|
|
8
|
+
* 主线程 → worker: { id, op: 'all'|'get'|'run'|'exec'|'batch'|'close', sql?, params?, statements? }
|
|
9
|
+
* worker → 主线程: { id, ok, result } | { id, ok:false, error:{ message } } | { type:'ready'|'init-error' }
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { createRequire } from 'node:module'
|
|
13
|
+
import { parentPort, workerData } from 'node:worker_threads'
|
|
14
|
+
|
|
15
|
+
const require = createRequire(import.meta.url)
|
|
16
|
+
|
|
17
|
+
if (!parentPort) {
|
|
18
|
+
throw new Error('reldb sqlite worker must run inside a worker thread')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 归一化错误为可结构化克隆的对象。 */
|
|
22
|
+
function serializeError(error) {
|
|
23
|
+
return { message: error instanceof Error ? error.message : String(error) }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** 打开数据库连接并按需启用 WAL。 */
|
|
27
|
+
function openDatabase() {
|
|
28
|
+
const Database = require('better-sqlite3')
|
|
29
|
+
const database = new Database(workerData.database, { readonly: workerData.readonly ?? false })
|
|
30
|
+
if (workerData.walMode !== false) {
|
|
31
|
+
database.pragma('journal_mode = WAL')
|
|
32
|
+
}
|
|
33
|
+
return database
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let db = null
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
db = openDatabase()
|
|
40
|
+
parentPort.postMessage({ type: 'ready' })
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
parentPort.postMessage({ type: 'init-error', error: serializeError(error) })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
parentPort.on('message', (msg) => {
|
|
47
|
+
const { id, op, sql, params, statements } = msg
|
|
48
|
+
|
|
49
|
+
if (op === 'close') {
|
|
50
|
+
try {
|
|
51
|
+
db?.close()
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// 忽略关闭异常,仍需回执并退出。
|
|
55
|
+
}
|
|
56
|
+
db = null
|
|
57
|
+
parentPort.postMessage({ id, ok: true, result: undefined })
|
|
58
|
+
parentPort.close()
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (!db)
|
|
64
|
+
throw new Error('sqlite worker database is not open')
|
|
65
|
+
|
|
66
|
+
let result
|
|
67
|
+
switch (op) {
|
|
68
|
+
case 'all': {
|
|
69
|
+
const stmt = db.prepare(sql)
|
|
70
|
+
result = params ? stmt.all(...params) : stmt.all()
|
|
71
|
+
break
|
|
72
|
+
}
|
|
73
|
+
case 'get': {
|
|
74
|
+
const stmt = db.prepare(sql)
|
|
75
|
+
result = (params ? stmt.get(...params) : stmt.get()) ?? null
|
|
76
|
+
break
|
|
77
|
+
}
|
|
78
|
+
case 'run': {
|
|
79
|
+
const stmt = db.prepare(sql)
|
|
80
|
+
const runResult = params ? stmt.run(...params) : stmt.run()
|
|
81
|
+
result = { changes: runResult.changes, lastInsertRowid: runResult.lastInsertRowid }
|
|
82
|
+
break
|
|
83
|
+
}
|
|
84
|
+
case 'exec': {
|
|
85
|
+
db.exec(sql)
|
|
86
|
+
result = undefined
|
|
87
|
+
break
|
|
88
|
+
}
|
|
89
|
+
case 'batch': {
|
|
90
|
+
const database = db
|
|
91
|
+
const tx = database.transaction((items) => {
|
|
92
|
+
for (const item of items) {
|
|
93
|
+
const stmt = database.prepare(item.sql)
|
|
94
|
+
if (item.params)
|
|
95
|
+
stmt.run(...item.params)
|
|
96
|
+
else stmt.run()
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
tx(statements)
|
|
100
|
+
result = undefined
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
default:
|
|
104
|
+
throw new Error(`unknown sqlite worker op: ${op}`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
parentPort.postMessage({ id, ok: true, result })
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
parentPort.postMessage({ id, ok: false, error: serializeError(error) })
|
|
111
|
+
}
|
|
112
|
+
})
|
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.
|
|
4
|
+
"version": "0.1.0-alpha.50",
|
|
5
5
|
"description": "Hai Framework relational database module for SQLite, PostgreSQL, and MySQL.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"exports": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"better-sqlite3": "^12.6.2",
|
|
24
24
|
"zod": "^4.4.3",
|
|
25
|
-
"@h-ai/core": "0.1.0-alpha.
|
|
25
|
+
"@h-ai/core": "0.1.0-alpha.50"
|
|
26
26
|
},
|
|
27
27
|
"optionalDependencies": {
|
|
28
28
|
"mysql2": "^3.11.5",
|