@dangao/bun-server 3.0.0 → 3.0.1

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.
@@ -10932,8 +10932,8 @@ class ConnectionPool {
10932
10932
  const { Database } = await import("bun:sqlite");
10933
10933
  return new Database(config.path);
10934
10934
  }
10935
- const BetterSqlite3 = __require("better-sqlite3");
10936
- return BetterSqlite3(config.path);
10935
+ const sqlite3 = __require("@vscode/sqlite3");
10936
+ return new sqlite3.Database(config.path);
10937
10937
  }
10938
10938
  async createPostgresConnection(config) {
10939
10939
  const url = `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
@@ -11099,11 +11099,25 @@ class DatabaseConnectionManager {
11099
11099
  }
11100
11100
  async healthCheckSqlite(connection) {
11101
11101
  try {
11102
- if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
11102
+ if (!connection || typeof connection !== "object") {
11103
+ return false;
11104
+ }
11105
+ if ("query" in connection && typeof connection.query === "function" && !(("all" in connection) && ("run" in connection))) {
11103
11106
  const db = connection;
11104
11107
  db.query("SELECT 1").all();
11105
11108
  return true;
11106
11109
  }
11110
+ if ("all" in connection && typeof connection.all === "function") {
11111
+ await new Promise((resolve2, reject) => {
11112
+ connection.all("SELECT 1", [], (err) => {
11113
+ if (err)
11114
+ reject(err);
11115
+ else
11116
+ resolve2();
11117
+ });
11118
+ });
11119
+ return true;
11120
+ }
11107
11121
  return false;
11108
11122
  } catch (_error) {
11109
11123
  return false;
@@ -11213,12 +11227,22 @@ class DatabaseService2 {
11213
11227
  throw new Error(`Query not supported for database type: ${dbType}`);
11214
11228
  }
11215
11229
  querySqlite(connection, sql, params) {
11216
- if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
11230
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function" && !(("all" in connection) && ("run" in connection))) {
11217
11231
  const db = connection;
11218
11232
  const statement = db.query(sql);
11219
11233
  const result = params && params.length > 0 ? statement.all(...params) : statement.all();
11220
11234
  return result;
11221
11235
  }
11236
+ if (connection && typeof connection === "object" && "all" in connection && typeof connection.all === "function") {
11237
+ return new Promise((resolve2, reject) => {
11238
+ connection.all(sql, params ?? [], (err, rows) => {
11239
+ if (err)
11240
+ reject(err);
11241
+ else
11242
+ resolve2(rows ?? []);
11243
+ });
11244
+ });
11245
+ }
11222
11246
  throw new Error("Invalid SQLite connection");
11223
11247
  }
11224
11248
  async queryBunSQL(connection, sql, params) {
@@ -11389,24 +11413,29 @@ class SqliteAdapter {
11389
11413
  }
11390
11414
  this.db = db;
11391
11415
  } else {
11392
- const BetterSqlite3 = __require("better-sqlite3");
11393
- const db = BetterSqlite3(config.database);
11416
+ const sqlite3 = __require("@vscode/sqlite3");
11417
+ const db = new sqlite3.Database(config.database);
11394
11418
  if (config.wal !== false) {
11395
- db.exec("PRAGMA journal_mode = WAL;");
11419
+ db.run("PRAGMA journal_mode = WAL;");
11396
11420
  }
11397
11421
  this.db = db;
11398
11422
  }
11399
11423
  this.semaphore = new Semaphore(config.maxWriteConcurrency ?? 1);
11400
11424
  }
11401
- query(sql, params = []) {
11425
+ async query(sql, params = []) {
11402
11426
  if (this.isBun) {
11403
- const db2 = this.db;
11404
- const stmt2 = db2.query(sql);
11405
- return stmt2.all(...params);
11427
+ const db = this.db;
11428
+ const stmt = db.query(sql);
11429
+ return stmt.all(...params);
11406
11430
  }
11407
- const db = this.db;
11408
- const stmt = db.prepare(sql);
11409
- return stmt.all(...params);
11431
+ return new Promise((resolve2, reject) => {
11432
+ this.db.all(sql, params, (err, rows) => {
11433
+ if (err)
11434
+ reject(err);
11435
+ else
11436
+ resolve2(rows ?? []);
11437
+ });
11438
+ });
11410
11439
  }
11411
11440
  async execute(sql, params = []) {
11412
11441
  if (this.isBun) {
@@ -11414,9 +11443,14 @@ class SqliteAdapter {
11414
11443
  const stmt = db.query(sql);
11415
11444
  stmt.run(...params);
11416
11445
  } else {
11417
- const db = this.db;
11418
- const stmt = db.prepare(sql);
11419
- stmt.run(...params);
11446
+ return new Promise((resolve2, reject) => {
11447
+ this.db.run(sql, params, (err) => {
11448
+ if (err)
11449
+ reject(err);
11450
+ else
11451
+ resolve2();
11452
+ });
11453
+ });
11420
11454
  }
11421
11455
  }
11422
11456
  close() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dangao/bun-server",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -50,7 +50,7 @@
50
50
  "test:platform": "bun run test:bun && bun run test:node",
51
51
  "type-check": "tsc --noEmit",
52
52
  "clean": "rm -rf dist",
53
- "bundle": "bun build src/index.ts --target=bun --format=esm --outfile=dist/index.js --external reflect-metadata --external @dangao/logsmith --external @dangao/nacos-client",
53
+ "bundle": "bun build src/index.ts --target=bun --format=esm --outfile=dist/index.js --external reflect-metadata --external @dangao/logsmith --external @dangao/nacos-client --external @vscode/sqlite3",
54
54
  "bundle:node": "bun build src/index.ts --target=node --packages=external --outfile=dist/index.node.mjs",
55
55
  "dts": "tsc -p tsconfig.build.json",
56
56
  "build": "bun run clean && bun run bundle && bun run bundle:node && bun run dts",
@@ -59,7 +59,6 @@
59
59
  "publish:package:github": "cp -r ../../README.md ../../LICENSE ../../docs . && bun pm pack --access public && npm publish *.tgz --provenance --access public && rm -rf ./README.md ./LICENSE ./docs"
60
60
  },
61
61
  "devDependencies": {
62
- "@types/better-sqlite3": "^7.6.13",
63
62
  "@types/bun": "^1.3.10",
64
63
  "@types/mime-types": "^3.0.1",
65
64
  "@types/ws": "^8.18.1",
@@ -69,7 +68,7 @@
69
68
  "dependencies": {
70
69
  "@dangao/logsmith": "0.2.0",
71
70
  "@dangao/nacos-client": "0.1.1",
72
- "better-sqlite3": "^12.8.0",
71
+ "@vscode/sqlite3": "5.1.12-vscode",
73
72
  "json5": "^2.2.3",
74
73
  "jsonc-parser": "^3.3.1",
75
74
  "marked": "^18.0.0",
@@ -160,21 +160,28 @@ export class DatabaseConnectionManager {
160
160
  */
161
161
  private async healthCheckSqlite(connection: unknown): Promise<boolean> {
162
162
  try {
163
- if (
164
- connection &&
165
- typeof connection === 'object' &&
166
- 'query' in connection &&
167
- typeof connection.query === 'function'
168
- ) {
169
- // 执行简单的查询来检查连接
170
- const db = connection as {
171
- query: (sql: string) => {
172
- all: () => unknown[];
173
- };
174
- };
163
+ if (!connection || typeof connection !== 'object') {
164
+ return false;
165
+ }
166
+
167
+ // bun:sqlite Database(有 .query() 但没有 callback-based .all())
168
+ if ('query' in connection && typeof (connection as any).query === 'function' && !('all' in connection && 'run' in connection)) {
169
+ const db = connection as { query: (sql: string) => { all: () => unknown[] } };
175
170
  db.query('SELECT 1').all();
176
171
  return true;
177
172
  }
173
+
174
+ // @vscode/sqlite3 Database(callback-based .all())
175
+ if ('all' in connection && typeof (connection as any).all === 'function') {
176
+ await new Promise<void>((resolve, reject) => {
177
+ (connection as any).all('SELECT 1', [], (err: Error | null) => {
178
+ if (err) reject(err);
179
+ else resolve();
180
+ });
181
+ });
182
+ return true;
183
+ }
184
+
178
185
  return false;
179
186
  } catch (_error) {
180
187
  return false;
@@ -185,9 +185,10 @@ export class ConnectionPool {
185
185
  const { Database } = await import('bun:sqlite');
186
186
  return new Database(config.path);
187
187
  }
188
- // Node.js:使用 better-sqlite3
189
- const BetterSqlite3 = require('better-sqlite3') as typeof import('better-sqlite3');
190
- return BetterSqlite3(config.path);
188
+ // Node.js:使用 @vscode/sqlite3
189
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
190
+ const sqlite3 = require('@vscode/sqlite3') as any;
191
+ return new sqlite3.Database(config.path);
191
192
  }
192
193
 
193
194
  /**
@@ -113,7 +113,7 @@ export class DatabaseService {
113
113
 
114
114
  /**
115
115
  * 执行 SQL 查询
116
- * SQLite 返回同步结果,PostgreSQL/MySQL 返回异步结果
116
+ * SQLite (bun:sqlite) 返回同步结果;@vscode/sqlite3 / PostgreSQL / MySQL 返回异步结果
117
117
  */
118
118
  public query<T = unknown>(sql: string, params?: unknown[]): T[] | Promise<T[]> {
119
119
  const session = getCurrentSession();
@@ -139,18 +139,20 @@ export class DatabaseService {
139
139
 
140
140
  /**
141
141
  * SQLite 查询实现
142
+ * bun:sqlite 使用同步 .query().all();@vscode/sqlite3 使用异步 callback .all()
142
143
  */
143
144
  private querySqlite<T = unknown>(
144
145
  connection: unknown,
145
146
  sql: string,
146
147
  params?: unknown[],
147
- ): T[] {
148
- // Bun SQLite Database 对象
148
+ ): T[] | Promise<T[]> {
149
+ // bun:sqlite Database 对象(有 .query() 方法)
149
150
  if (
150
151
  connection &&
151
152
  typeof connection === 'object' &&
152
153
  'query' in connection &&
153
- typeof connection.query === 'function'
154
+ typeof (connection as any).query === 'function' &&
155
+ !('all' in connection && 'run' in connection)
154
156
  ) {
155
157
  const db = connection as {
156
158
  query: (sql: string) => {
@@ -160,12 +162,26 @@ export class DatabaseService {
160
162
  };
161
163
 
162
164
  const statement = db.query(sql);
163
- // Bun SQLite 的 all() 方法接受参数
164
165
  const result =
165
166
  params && params.length > 0 ? statement.all(...params) : statement.all();
166
167
  return result;
167
168
  }
168
169
 
170
+ // @vscode/sqlite3 Database 对象(有 .all() callback 方法)
171
+ if (
172
+ connection &&
173
+ typeof connection === 'object' &&
174
+ 'all' in connection &&
175
+ typeof (connection as any).all === 'function'
176
+ ) {
177
+ return new Promise<T[]>((resolve, reject) => {
178
+ (connection as any).all(sql, params ?? [], (err: Error | null, rows: T[]) => {
179
+ if (err) reject(err);
180
+ else resolve(rows ?? []);
181
+ });
182
+ });
183
+ }
184
+
169
185
  throw new Error('Invalid SQLite connection');
170
186
  }
171
187
 
@@ -40,7 +40,7 @@ export class Semaphore {
40
40
 
41
41
  /**
42
42
  * SQLite 适配器(自动感知运行时)
43
- * Bun 平台下使用 bun:sqlite,Node.js 平台下使用 better-sqlite3
43
+ * Bun 平台下使用 bun:sqlite,Node.js 平台下使用 @vscode/sqlite3
44
44
  */
45
45
  export class SqliteAdapter {
46
46
  private readonly db: unknown;
@@ -58,10 +58,12 @@ export class SqliteAdapter {
58
58
  }
59
59
  this.db = db;
60
60
  } else {
61
- const BetterSqlite3 = require('better-sqlite3') as typeof import('better-sqlite3');
62
- const db = BetterSqlite3(config.database);
61
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
62
+ const sqlite3 = require('@vscode/sqlite3') as any;
63
+ const db: any = new sqlite3.Database(config.database);
63
64
  if (config.wal !== false) {
64
- db.exec('PRAGMA journal_mode = WAL;');
65
+ // Operations are serialized internally; WAL is queued before any query runs
66
+ db.run('PRAGMA journal_mode = WAL;');
65
67
  }
66
68
  this.db = db;
67
69
  }
@@ -69,15 +71,18 @@ export class SqliteAdapter {
69
71
  this.semaphore = new Semaphore(config.maxWriteConcurrency ?? 1);
70
72
  }
71
73
 
72
- public query<T = unknown>(sql: string, params: unknown[] = []): T[] {
74
+ public async query<T = unknown>(sql: string, params: unknown[] = []): Promise<T[]> {
73
75
  if (this.isBun) {
74
76
  const db = this.db as import('bun:sqlite').Database;
75
77
  const stmt = db.query(sql);
76
78
  return stmt.all(...params as Parameters<typeof stmt.all>) as T[];
77
79
  }
78
- const db = this.db as import('better-sqlite3').Database;
79
- const stmt = db.prepare(sql);
80
- return stmt.all(...params) as T[];
80
+ return new Promise<T[]>((resolve, reject) => {
81
+ (this.db as any).all(sql, params, (err: Error | null, rows: T[]) => {
82
+ if (err) reject(err);
83
+ else resolve(rows ?? []);
84
+ });
85
+ });
81
86
  }
82
87
 
83
88
  public async execute(sql: string, params: unknown[] = []): Promise<void> {
@@ -86,9 +91,12 @@ export class SqliteAdapter {
86
91
  const stmt = db.query(sql);
87
92
  stmt.run(...params as Parameters<typeof stmt.run>);
88
93
  } else {
89
- const db = this.db as import('better-sqlite3').Database;
90
- const stmt = db.prepare(sql);
91
- stmt.run(...params);
94
+ return new Promise<void>((resolve, reject) => {
95
+ (this.db as any).run(sql, params, (err: Error | null) => {
96
+ if (err) reject(err);
97
+ else resolve();
98
+ });
99
+ });
92
100
  }
93
101
  }
94
102
 
@@ -7,22 +7,22 @@ import { SqliteManager } from '../../../src/database/sqlite-adapter';
7
7
  export function runDatabaseCases(suite: TestSuite, engine: PlatformEngine): void {
8
8
  const { test, expect } = suite;
9
9
 
10
- // better-sqlite3 is not supported when running Node-platform tests under Bun runtime
11
- const skipBetterSqlite = engine === 'node' && typeof (globalThis as any).Bun !== 'undefined';
10
+ // @vscode/sqlite3 is a native Node.js addon; skip when Node-platform tests run under Bun runtime
11
+ const skipNodeSqlite = engine === 'node' && typeof (globalThis as any).Bun !== 'undefined';
12
12
 
13
- test('SqliteAdapter: create table, insert and query', () => {
14
- if (skipBetterSqlite) {
15
- // better-sqlite3 is not supported in Bun — this test must run under Node.js
16
- console.log('[skip] better-sqlite3 not available in Bun runtime; run with vitest for Node platform');
13
+ test('SqliteAdapter: create table, insert and query', async () => {
14
+ if (skipNodeSqlite) {
15
+ // @vscode/sqlite3 is not available in Bun — this test must run under Node.js
16
+ console.log('[skip] @vscode/sqlite3 not available in Bun runtime; run with vitest for Node platform');
17
17
  return;
18
18
  }
19
19
  const dbPath = join(tmpdir(), `platform-db-test-${engine}-${Date.now()}.db`);
20
20
  const manager = new SqliteManager();
21
21
  const adapter = manager.getOrCreate('test', { database: dbPath, wal: false });
22
22
 
23
- adapter.query('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
24
- adapter.query("INSERT INTO users (name) VALUES ('Alice')");
25
- const rows = adapter.query<{ id: number; name: string }>('SELECT * FROM users');
23
+ await adapter.query('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)');
24
+ await adapter.query("INSERT INTO users (name) VALUES ('Alice')");
25
+ const rows = await adapter.query<{ id: number; name: string }>('SELECT * FROM users');
26
26
 
27
27
  expect(rows.length).toBeGreaterThanOrEqual(1);
28
28
  expect(rows[0]!.name).toBe('Alice');