@dangao/bun-server 3.1.0 → 3.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.
@@ -10865,6 +10865,197 @@ init_decorators();
10865
10865
  // src/database/connection-pool.ts
10866
10866
  init_runtime();
10867
10867
 
10868
+ // src/database/driver.ts
10869
+ var DRIVER_TAG = Symbol.for("@dangao/bun-server:database:driver");
10870
+ function resolveDriver(dbType, option, engine) {
10871
+ const driver = option ?? "auto";
10872
+ switch (driver) {
10873
+ case "auto":
10874
+ if (engine === "bun") {
10875
+ return "bun-sql";
10876
+ }
10877
+ return dbType === "mysql" ? "mysql2" : "postgres";
10878
+ case "bun-sql":
10879
+ if (engine !== "bun") {
10880
+ throw new Error(`[bun-server] driver 'bun-sql' requires the Bun runtime, but the current platform engine is '${engine}'. ` + `Use driver 'auto' / 'mysql2' / 'postgres', or run on Bun.`);
10881
+ }
10882
+ return "bun-sql";
10883
+ case "mysql2":
10884
+ if (dbType !== "mysql") {
10885
+ throw new Error(`[bun-server] driver 'mysql2' is only valid for type 'mysql', but got type '${dbType}'.`);
10886
+ }
10887
+ return "mysql2";
10888
+ case "postgres":
10889
+ if (dbType !== "postgres") {
10890
+ throw new Error(`[bun-server] driver 'postgres' is only valid for type 'postgres', but got type '${dbType}'.`);
10891
+ }
10892
+ return "postgres";
10893
+ default:
10894
+ throw new Error(`[bun-server] unknown driver '${String(driver)}'.`);
10895
+ }
10896
+ }
10897
+ function tagConnection(connection, driver) {
10898
+ if (connection && (typeof connection === "object" || typeof connection === "function")) {
10899
+ try {
10900
+ Object.defineProperty(connection, DRIVER_TAG, {
10901
+ value: driver,
10902
+ enumerable: false,
10903
+ configurable: true,
10904
+ writable: true
10905
+ });
10906
+ } catch {}
10907
+ }
10908
+ return connection;
10909
+ }
10910
+ function getConnectionDriver(connection) {
10911
+ if (!connection) {
10912
+ return;
10913
+ }
10914
+ if (typeof connection === "object" || typeof connection === "function") {
10915
+ const tagged = connection[DRIVER_TAG];
10916
+ if (tagged === "bun-sql" || tagged === "mysql2" || tagged === "postgres") {
10917
+ return tagged;
10918
+ }
10919
+ }
10920
+ if (typeof connection === "function") {
10921
+ return "bun-sql";
10922
+ }
10923
+ return;
10924
+ }
10925
+ async function createPostgresConnection(config, driver) {
10926
+ const url = `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
10927
+ if (driver === "bun-sql") {
10928
+ const { SQL } = await import("bun");
10929
+ return tagConnection(new SQL({
10930
+ adapter: "postgres",
10931
+ hostname: config.host,
10932
+ port: config.port,
10933
+ username: config.user,
10934
+ password: config.password,
10935
+ database: config.database,
10936
+ max: 1,
10937
+ tls: config.ssl ?? false
10938
+ }), "bun-sql");
10939
+ }
10940
+ if (driver === "postgres") {
10941
+ const postgres = loadPostgres();
10942
+ return tagConnection(postgres(url, { max: 1, ssl: config.ssl ? "require" : false }), "postgres");
10943
+ }
10944
+ throw new Error(`[bun-server] driver '${driver}' cannot create a postgres connection.`);
10945
+ }
10946
+ async function createMysqlConnection(config, driver) {
10947
+ if (driver === "bun-sql") {
10948
+ const { SQL } = await import("bun");
10949
+ return tagConnection(new SQL({
10950
+ adapter: "mysql",
10951
+ hostname: config.host,
10952
+ port: config.port,
10953
+ username: config.user,
10954
+ password: config.password,
10955
+ database: config.database,
10956
+ max: 1,
10957
+ ssl: config.ssl ?? false
10958
+ }), "bun-sql");
10959
+ }
10960
+ if (driver === "mysql2") {
10961
+ const mysql2 = loadMysql2();
10962
+ const conn = await mysql2.createConnection({
10963
+ host: config.host,
10964
+ port: config.port,
10965
+ database: config.database,
10966
+ user: config.user,
10967
+ password: config.password
10968
+ });
10969
+ return tagConnection(conn, "mysql2");
10970
+ }
10971
+ throw new Error(`[bun-server] driver '${driver}' cannot create a mysql connection.`);
10972
+ }
10973
+ async function queryViaDriver(connection, sql, params) {
10974
+ const driver = getConnectionDriver(connection);
10975
+ if (driver === "mysql2") {
10976
+ const conn = connection;
10977
+ const [rows] = await conn.query(sql, params ?? []);
10978
+ return rows ?? [];
10979
+ }
10980
+ if (driver === "postgres") {
10981
+ const conn = connection;
10982
+ const rows = await conn.unsafe(sql, params ?? []);
10983
+ return rows ?? [];
10984
+ }
10985
+ if (typeof connection === "function") {
10986
+ const { strings, values } = buildTemplateFromSql(sql, params);
10987
+ const template = Object.assign(strings.slice(), {
10988
+ raw: strings.slice()
10989
+ });
10990
+ const result = await connection(template, ...values);
10991
+ return result;
10992
+ }
10993
+ if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
10994
+ const result = await connection.query(sql, params ?? []);
10995
+ return Array.isArray(result) ? result[0] : result;
10996
+ }
10997
+ throw new Error("[bun-server] invalid SQL connection for query.");
10998
+ }
10999
+ async function templateQueryViaDriver(connection, strings, values) {
11000
+ const driver = getConnectionDriver(connection);
11001
+ if (driver === "mysql2") {
11002
+ const sql = strings.join("?");
11003
+ const conn = connection;
11004
+ const [rows] = await conn.query(sql, values);
11005
+ return rows;
11006
+ }
11007
+ return await connection(strings, ...values);
11008
+ }
11009
+ async function healthCheckViaDriver(connection) {
11010
+ try {
11011
+ const rows = await queryViaDriver(connection, "SELECT 1");
11012
+ return Array.isArray(rows);
11013
+ } catch {
11014
+ return false;
11015
+ }
11016
+ }
11017
+ async function closeViaDriver(connection) {
11018
+ if (!connection || typeof connection !== "object" && typeof connection !== "function") {
11019
+ return;
11020
+ }
11021
+ const driver = getConnectionDriver(connection);
11022
+ const conn = connection;
11023
+ if (driver === "mysql2" || driver === "postgres") {
11024
+ if (typeof conn.end === "function") {
11025
+ await conn.end();
11026
+ return;
11027
+ }
11028
+ }
11029
+ if (driver === "bun-sql") {
11030
+ if (typeof conn.close === "function") {
11031
+ await conn.close();
11032
+ return;
11033
+ }
11034
+ }
11035
+ if (typeof conn.close === "function") {
11036
+ await conn.close();
11037
+ } else if (typeof conn.end === "function") {
11038
+ await conn.end();
11039
+ }
11040
+ }
11041
+ function buildTemplateFromSql(sql, params) {
11042
+ if (!params || params.length === 0) {
11043
+ return { strings: [sql], values: [] };
11044
+ }
11045
+ const strings = sql.split("?");
11046
+ if (strings.length !== params.length + 1) {
11047
+ throw new Error("SQL placeholders count does not match parameters count");
11048
+ }
11049
+ return { strings, values: params };
11050
+ }
11051
+ function loadMysql2() {
11052
+ return __require("mysql2/promise");
11053
+ }
11054
+ function loadPostgres() {
11055
+ return __require("postgres");
11056
+ }
11057
+
11058
+ // src/database/connection-pool.ts
10868
11059
  class ConnectionPool {
10869
11060
  config;
10870
11061
  options;
@@ -10979,29 +11170,12 @@ Install it with: bun add @vscode/sqlite3@5.1.12-vscode`);
10979
11170
  return new sqlite3.Database(config.path);
10980
11171
  }
10981
11172
  async createPostgresConnection(config) {
10982
- const url = `postgres://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
10983
- if (getRuntime().engine === "bun") {
10984
- const { SQL } = await import("bun");
10985
- return new SQL(url, { max: 1, tls: config.ssl ?? false });
10986
- }
10987
- const postgres = __require("postgres");
10988
- return postgres(url, { max: 1, ssl: config.ssl ? "require" : false });
11173
+ const driver = resolveDriver("postgres", this.config.type === "postgres" ? this.config.driver : undefined, getRuntime().engine);
11174
+ return await createPostgresConnection(config, driver);
10989
11175
  }
10990
11176
  async createMysqlConnection(config) {
10991
- if (getRuntime().engine === "bun") {
10992
- const url = `mysql://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}`;
10993
- const { SQL } = await import("bun");
10994
- return new SQL(url, { max: 1 });
10995
- }
10996
- const mysql2 = __require("mysql2/promise");
10997
- const conn = await mysql2.createConnection({
10998
- host: config.host,
10999
- port: config.port,
11000
- database: config.database,
11001
- user: config.user,
11002
- password: config.password
11003
- });
11004
- return conn;
11177
+ const driver = resolveDriver("mysql", this.config.type === "mysql" ? this.config.driver : undefined, getRuntime().engine);
11178
+ return await createMysqlConnection(config, driver);
11005
11179
  }
11006
11180
  async closeConnection(connection) {
11007
11181
  const dbType = this.config.type;
@@ -11018,15 +11192,11 @@ Install it with: bun add @vscode/sqlite3@5.1.12-vscode`);
11018
11192
  connection.close();
11019
11193
  }
11020
11194
  }
11021
- async closePostgresConnection(_connection) {
11022
- if (_connection && typeof _connection === "object" && "close" in _connection && typeof _connection.close === "function") {
11023
- _connection.close();
11024
- }
11195
+ async closePostgresConnection(connection) {
11196
+ await closeViaDriver(connection);
11025
11197
  }
11026
- async closeMysqlConnection(_connection) {
11027
- if (_connection && typeof _connection === "object" && "close" in _connection && typeof _connection.close === "function") {
11028
- _connection.close();
11029
- }
11198
+ async closeMysqlConnection(connection) {
11199
+ await closeViaDriver(connection);
11030
11200
  }
11031
11201
  async waitForConnection() {
11032
11202
  const startTime = Date.now();
@@ -11167,34 +11337,10 @@ class DatabaseConnectionManager {
11167
11337
  }
11168
11338
  }
11169
11339
  async healthCheckPostgres(connection) {
11170
- try {
11171
- if (connection && typeof connection === "function") {
11172
- const result = await connection`SELECT 1`;
11173
- return Array.isArray(result) && result.length > 0;
11174
- }
11175
- if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
11176
- await connection.query("SELECT 1");
11177
- return true;
11178
- }
11179
- return false;
11180
- } catch (_error) {
11181
- return false;
11182
- }
11340
+ return await healthCheckViaDriver(connection);
11183
11341
  }
11184
11342
  async healthCheckMysql(connection) {
11185
- try {
11186
- if (connection && typeof connection === "function") {
11187
- const result = await connection`SELECT 1`;
11188
- return Array.isArray(result) && result.length > 0;
11189
- }
11190
- if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
11191
- await connection.query("SELECT 1");
11192
- return true;
11193
- }
11194
- return false;
11195
- } catch (_error) {
11196
- return false;
11197
- }
11343
+ return await healthCheckViaDriver(connection);
11198
11344
  }
11199
11345
  }
11200
11346
 
@@ -11265,7 +11411,7 @@ class DatabaseService2 {
11265
11411
  if (dbType === "sqlite") {
11266
11412
  return this.querySqlite(connection, sql, params);
11267
11413
  } else if (dbType === "postgres" || dbType === "mysql") {
11268
- return this.queryBunSQL(connection, sql, params);
11414
+ return queryViaDriver(connection, sql, params);
11269
11415
  }
11270
11416
  throw new Error(`Query not supported for database type: ${dbType}`);
11271
11417
  }
@@ -11288,37 +11434,6 @@ class DatabaseService2 {
11288
11434
  }
11289
11435
  throw new Error("Invalid SQLite connection");
11290
11436
  }
11291
- async queryBunSQL(connection, sql, params) {
11292
- if (connection && typeof connection === "function") {
11293
- try {
11294
- const { strings, values } = this.buildTemplateFromSql(sql, params);
11295
- const template = Object.assign(strings, {
11296
- raw: strings
11297
- });
11298
- const result = await connection(template, ...values);
11299
- return result;
11300
- } catch (error) {
11301
- const errorMessage = error instanceof Error ? error.message : String(error);
11302
- throw new Error(`Bun.SQL parameterized queries are not fully supported. Consider using template string queries. Original error: ${errorMessage}`);
11303
- }
11304
- }
11305
- if (connection && typeof connection === "object" && "query" in connection && typeof connection.query === "function") {
11306
- const db = connection;
11307
- const result = await db.query(sql, ...params ?? []);
11308
- return result;
11309
- }
11310
- throw new Error("Invalid Bun.SQL connection");
11311
- }
11312
- buildTemplateFromSql(sql, params) {
11313
- if (!params || params.length === 0) {
11314
- return { strings: [sql], values: [] };
11315
- }
11316
- const strings = sql.split("?");
11317
- if (strings.length !== params.length + 1) {
11318
- throw new Error("SQL placeholders count does not match parameters count");
11319
- }
11320
- return { strings, values: params };
11321
- }
11322
11437
  }
11323
11438
  DatabaseService2 = __legacyDecorateClassTS([
11324
11439
  Injectable(),
@@ -11332,7 +11447,6 @@ var ORM_SERVICE_TOKEN = Symbol("@dangao/bun-server:orm:service");
11332
11447
 
11333
11448
  // src/database/sql-manager.ts
11334
11449
  init_runtime();
11335
-
11336
11450
  class BunSQLManager2 {
11337
11451
  instances = new Map;
11338
11452
  defaultTenantId = "default";
@@ -11342,34 +11456,49 @@ class BunSQLManager2 {
11342
11456
  return existing;
11343
11457
  }
11344
11458
  const pool = config.pool ?? {};
11459
+ const driver = resolveDriver(config.type, config.driver, getRuntime().engine);
11345
11460
  let sql;
11346
- if (getRuntime().engine === "bun") {
11461
+ if (driver === "bun-sql") {
11347
11462
  const { SQL } = __require("bun");
11348
- sql = new SQL(config.url, {
11349
- max: pool.max ?? 10,
11350
- idleTimeout: pool.idleTimeout ?? 30,
11351
- maxLifetime: pool.maxLifetime ?? 0,
11352
- connectionTimeout: pool.connectionTimeout ?? 30000
11353
- });
11354
- } else {
11355
- const url = config.url.toLowerCase();
11356
- if (url.startsWith("mysql://") || url.startsWith("mysql2://")) {
11357
- const mysql2 = __require("mysql2/promise");
11358
- sql = mysql2.createPool({
11359
- uri: config.url,
11360
- connectionLimit: pool.max ?? 10,
11361
- waitForConnections: true
11463
+ if (config.type === "mysql") {
11464
+ const parsed = new URL(config.url);
11465
+ sql = new SQL({
11466
+ adapter: "mysql",
11467
+ hostname: parsed.hostname,
11468
+ port: parsed.port ? Number(parsed.port) : 3306,
11469
+ username: decodeURIComponent(parsed.username),
11470
+ password: decodeURIComponent(parsed.password),
11471
+ database: parsed.pathname.replace(/^\//, ""),
11472
+ max: pool.max ?? 10,
11473
+ idleTimeout: pool.idleTimeout ?? 30,
11474
+ maxLifetime: pool.maxLifetime ?? 0,
11475
+ connectionTimeout: pool.connectionTimeout ?? 30000
11362
11476
  });
11363
11477
  } else {
11364
- const postgres = __require("postgres");
11365
- sql = postgres(config.url, {
11478
+ sql = new SQL(config.url, {
11366
11479
  max: pool.max ?? 10,
11367
- idle_timeout: pool.idleTimeout ?? 30,
11368
- max_lifetime: pool.maxLifetime ?? 0,
11369
- connect_timeout: (pool.connectionTimeout ?? 30000) / 1000
11480
+ idleTimeout: pool.idleTimeout ?? 30,
11481
+ maxLifetime: pool.maxLifetime ?? 0,
11482
+ connectionTimeout: pool.connectionTimeout ?? 30000
11370
11483
  });
11371
11484
  }
11485
+ } else if (driver === "mysql2") {
11486
+ const mysql2 = __require("mysql2/promise");
11487
+ sql = mysql2.createPool({
11488
+ uri: config.url,
11489
+ connectionLimit: pool.max ?? 10,
11490
+ waitForConnections: true
11491
+ });
11492
+ } else {
11493
+ const postgres = __require("postgres");
11494
+ sql = postgres(config.url, {
11495
+ max: pool.max ?? 10,
11496
+ idle_timeout: pool.idleTimeout ?? 30,
11497
+ max_lifetime: pool.maxLifetime ?? 0,
11498
+ connect_timeout: (pool.connectionTimeout ?? 30000) / 1000
11499
+ });
11372
11500
  }
11501
+ tagConnection(sql, driver);
11373
11502
  this.instances.set(tenantId, sql);
11374
11503
  return sql;
11375
11504
  }
@@ -11580,10 +11709,10 @@ var baseDb = async (tenantId, strings, ...values) => {
11580
11709
  if (tenantId) {
11581
11710
  const tenantSql = sqlManager.get(tenantId);
11582
11711
  if (tenantSql) {
11583
- return await tenantSql(strings, ...values);
11712
+ return await templateQueryViaDriver(tenantSql, strings, values);
11584
11713
  }
11585
11714
  }
11586
- return await sqlManager.getDefault()(strings, ...values);
11715
+ return await templateQueryViaDriver(sqlManager.getDefault(), strings, values);
11587
11716
  };
11588
11717
  function createDb(tenantId) {
11589
11718
  const fn = async (strings, ...values) => baseDb(tenantId, strings, ...values);
@@ -11657,7 +11786,8 @@ class DatabaseModule {
11657
11786
  config: {
11658
11787
  type: db2.type,
11659
11788
  url,
11660
- pool: options.bunSqlPool
11789
+ pool: options.bunSqlPool,
11790
+ driver: db2.driver ?? options.driver
11661
11791
  }
11662
11792
  }
11663
11793
  ];
@@ -11682,7 +11812,8 @@ class DatabaseModule {
11682
11812
  config: {
11683
11813
  type: options.type,
11684
11814
  url: options.url,
11685
- pool: options.bunSqlPool
11815
+ pool: options.bunSqlPool,
11816
+ driver: options.driver
11686
11817
  }
11687
11818
  }
11688
11819
  ];
@@ -11696,7 +11827,8 @@ class DatabaseModule {
11696
11827
  config: {
11697
11828
  type: options.type,
11698
11829
  url,
11699
- pool: options.bunSqlPool
11830
+ pool: options.bunSqlPool,
11831
+ driver: options.driver
11700
11832
  }
11701
11833
  }
11702
11834
  ];
@@ -11780,7 +11912,8 @@ class DatabaseModule {
11780
11912
  database: options.databasePath ?? "default",
11781
11913
  user: options.username ?? "root",
11782
11914
  password: options.password ?? ""
11783
- }
11915
+ },
11916
+ driver: normalized[0]?.config?.driver ?? options.driver
11784
11917
  }
11785
11918
  };
11786
11919
  const service = new DatabaseService2(legacyOptions);
package/docs/database.md CHANGED
@@ -25,6 +25,50 @@ DatabaseModule.forRoot({
25
25
  });
26
26
  ```
27
27
 
28
+ ## Driver selection (decoupled from the runtime platform)
29
+
30
+ > Added in v3.2.0.
31
+
32
+ By default the underlying driver for Postgres/MySQL is chosen by the runtime platform: the Bun runtime uses the built-in `Bun.SQL`, while Node.js uses the pure-JS `mysql2` / `postgres` drivers.
33
+
34
+ The optional `driver` field lets you **explicitly pick a pure-JS driver even under the Bun runtime**, decoupled from the platform engine (fs/crypto/http server, etc.):
35
+
36
+ | driver | Behavior |
37
+ | --- | --- |
38
+ | `'auto'` (default) | Bun → `Bun.SQL`; Node → `mysql2` (MySQL) / `postgres` (PostgreSQL). Backward compatible. |
39
+ | `'mysql2'` | Always use `mysql2`, regardless of runtime (only for `type: 'mysql'`). |
40
+ | `'postgres'` | Always use `postgres`, regardless of runtime (only for `type: 'postgres'`). |
41
+ | `'bun-sql'` | Force `Bun.SQL` (valid on Bun only; throws a clear error on Node). |
42
+
43
+ ```ts
44
+ DatabaseModule.forRoot({
45
+ database: {
46
+ type: 'mysql',
47
+ driver: 'mysql2', // uses mysql2 even on the Bun runtime
48
+ config: {
49
+ host: '127.0.0.1',
50
+ port: 3306,
51
+ database: 'app',
52
+ user: 'root',
53
+ password: process.env.DB_PASSWORD!,
54
+ },
55
+ },
56
+ });
57
+
58
+ // The V2 single-tenant form is supported too:
59
+ DatabaseModule.forRoot({
60
+ type: 'mysql',
61
+ url: process.env.DB_URL!,
62
+ driver: 'mysql2',
63
+ });
64
+ ```
65
+
66
+ ### Why? MySQL under `bun build --compile`
67
+
68
+ A single binary produced by `bun build --compile` freezes the Bun runtime at build time, and the built-in `Bun.SQL` MySQL adapter has several known issues. Setting `driver: 'mysql2'` lets the compiled binary connect using the statically bundled pure-JS `mysql2` driver, without falling back to SQLite and without switching the whole platform via `BUN_SERVER_PLATFORM=node` (which would also move the HTTP server to Node).
69
+
70
+ The `driver` switch is orthogonal to `BUN_SERVER_PLATFORM`: the former only selects the SQL driver, while the latter selects the entire platform engine.
71
+
28
72
  ## Route strategy
29
73
 
30
74
  ```ts
@@ -25,6 +25,50 @@ DatabaseModule.forRoot({
25
25
  });
26
26
  ```
27
27
 
28
+ ## 驱动选择(driver,与运行时平台解耦)
29
+
30
+ > v3.2.0 新增。
31
+
32
+ 默认情况下,Postgres/MySQL 连接的底层驱动由运行时平台决定:Bun 运行时使用内建 `Bun.SQL`,Node.js 运行时使用 `mysql2` / `postgres` 纯 JS 驱动。
33
+
34
+ 通过可选的 `driver` 字段,可以**在 Bun 运行时下也显式选用纯 JS 驱动**,与平台引擎(fs/crypto/http server 等)解耦:
35
+
36
+ | driver | 行为 |
37
+ | --- | --- |
38
+ | `'auto'`(默认) | Bun → `Bun.SQL`;Node → `mysql2`(MySQL)/ `postgres`(PostgreSQL)。向后兼容。 |
39
+ | `'mysql2'` | 无论运行时如何,都使用 `mysql2`(仅 `type: 'mysql'`)。 |
40
+ | `'postgres'` | 无论运行时如何,都使用 `postgres`(仅 `type: 'postgres'`)。 |
41
+ | `'bun-sql'` | 强制使用 `Bun.SQL`(仅 Bun 合法,Node 会抛出清晰错误)。 |
42
+
43
+ ```ts
44
+ DatabaseModule.forRoot({
45
+ database: {
46
+ type: 'mysql',
47
+ driver: 'mysql2', // 即使在 Bun 运行时也走 mysql2
48
+ config: {
49
+ host: '127.0.0.1',
50
+ port: 3306,
51
+ database: 'app',
52
+ user: 'root',
53
+ password: process.env.DB_PASSWORD!,
54
+ },
55
+ },
56
+ });
57
+
58
+ // V2 单租户写法同样支持:
59
+ DatabaseModule.forRoot({
60
+ type: 'mysql',
61
+ url: process.env.DB_URL!,
62
+ driver: 'mysql2',
63
+ });
64
+ ```
65
+
66
+ ### 为什么需要它?`bun build --compile` 下的 MySQL
67
+
68
+ `bun build --compile` 产出的单二进制会把当时的 Bun 运行时焊死,其中内建 `Bun.SQL` 的 MySQL 适配带有若干已知问题。显式设置 `driver: 'mysql2'` 即可让编译产物使用静态打包的纯 JS `mysql2` 驱动连库,无需为此回退到 SQLite,也无需用 `BUN_SERVER_PLATFORM=node` 整体切平台(那会把 HTTP server 也切到 Node)。
69
+
70
+ `driver` 开关与 `BUN_SERVER_PLATFORM` 正交:前者只决定 SQL 驱动,后者决定整个平台引擎。
71
+
28
72
  ## 路由策略示例
29
73
 
30
74
  ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dangao/bun-server",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -7,6 +7,7 @@ import type {
7
7
  } from './types';
8
8
 
9
9
  import { ConnectionPool } from './connection-pool';
10
+ import { healthCheckViaDriver } from './driver';
10
11
 
11
12
  /**
12
13
  * 数据库连接管理器
@@ -189,58 +190,16 @@ export class DatabaseConnectionManager {
189
190
  }
190
191
 
191
192
  /**
192
- * PostgreSQL 健康检查(使用 Bun.SQL)
193
+ * PostgreSQL 健康检查(按连接 driver tag 分流)
193
194
  */
194
195
  private async healthCheckPostgres(connection: unknown): Promise<boolean> {
195
- try {
196
- // Bun.SQL 对象可以作为函数调用(模板字符串)
197
- if (connection && typeof connection === 'function') {
198
- const result = await (connection as (template: TemplateStringsArray, ...values: unknown[]) => Promise<unknown[]>)`SELECT 1`;
199
- return Array.isArray(result) && result.length > 0;
200
- }
201
- // 或者使用 query 方法(如果存在)
202
- if (
203
- connection &&
204
- typeof connection === 'object' &&
205
- 'query' in connection &&
206
- typeof connection.query === 'function'
207
- ) {
208
- await (connection as { query: (sql: string) => Promise<unknown> }).query(
209
- 'SELECT 1',
210
- );
211
- return true;
212
- }
213
- return false;
214
- } catch (_error) {
215
- return false;
216
- }
196
+ return await healthCheckViaDriver(connection);
217
197
  }
218
198
 
219
199
  /**
220
- * MySQL 健康检查(使用 Bun.SQL)
200
+ * MySQL 健康检查(按连接 driver tag 分流)
221
201
  */
222
202
  private async healthCheckMysql(connection: unknown): Promise<boolean> {
223
- try {
224
- // Bun.SQL 对象可以作为函数调用(模板字符串)
225
- if (connection && typeof connection === 'function') {
226
- const result = await (connection as (template: TemplateStringsArray, ...values: unknown[]) => Promise<unknown[]>)`SELECT 1`;
227
- return Array.isArray(result) && result.length > 0;
228
- }
229
- // 或者使用 query 方法(如果存在)
230
- if (
231
- connection &&
232
- typeof connection === 'object' &&
233
- 'query' in connection &&
234
- typeof connection.query === 'function'
235
- ) {
236
- await (connection as { query: (sql: string) => Promise<unknown> }).query(
237
- 'SELECT 1',
238
- );
239
- return true;
240
- }
241
- return false;
242
- } catch (_error) {
243
- return false;
244
- }
203
+ return await healthCheckViaDriver(connection);
245
204
  }
246
205
  }