tina4-nodejs 3.13.34 → 3.13.36

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.
@@ -161,6 +161,21 @@ export function setAdapter(adapter: DatabaseAdapter): DatabaseAdapter {
161
161
  return activeAdapter;
162
162
  }
163
163
 
164
+ /**
165
+ * Publish the live Database wrapper on `globalThis.__tina4_db` so framework
166
+ * tooling that runs outside the request/ORM path can reach it. The built-in
167
+ * MCP dev-tool handlers (database_query/execute/tables/columns, migration_*,
168
+ * seed_table, project_overview in `@tina4/core`'s mcp.ts) read this global; it
169
+ * is the single chokepoint every `initDatabase()` / `Database.create()` return
170
+ * path flows through, so the global is always set once a connection exists.
171
+ *
172
+ * Returns the same instance so it composes cleanly around a `return`.
173
+ */
174
+ function exposeDb(db: Database): Database {
175
+ (globalThis as any).__tina4_db = db;
176
+ return db;
177
+ }
178
+
164
179
  /**
165
180
  * Clear the request-scoped query cache on every live connection at the start of
166
181
  * each HTTP request, so request-scoped caching never serves rows across
@@ -535,7 +550,7 @@ export class Database {
535
550
  db.adapter = null; // Don't use single-adapter path
536
551
  db.adapterFactory = async () => wrapWithCache(await createAdapterFromUrl(url, username, password), { sharedCache });
537
552
  db.dbType = parsed.type;
538
- return db;
553
+ return exposeDb(db);
539
554
  }
540
555
 
541
556
  // Single-connection mode — wrap once and share the SAME wrapped adapter
@@ -545,7 +560,7 @@ export class Database {
545
560
  const wrapped = setAdapter(adapter);
546
561
  const db = new Database(wrapped);
547
562
  db.dbType = parsed.type;
548
- return db;
563
+ return exposeDb(db);
549
564
  }
550
565
 
551
566
  /**
@@ -1217,10 +1232,11 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1217
1232
  if (pool > 0) {
1218
1233
  // Pool-aware path — delegate to Database.create which manages
1219
1234
  // round-robin adapter rotation and async-local-storage transaction pinning.
1220
- return Database.create(url, resolvedUser, resolvedPassword, pool);
1235
+ // Database.create already exposes the global; exposeDb here is idempotent.
1236
+ return exposeDb(await Database.create(url, resolvedUser, resolvedPassword, pool));
1221
1237
  }
1222
1238
  const adapter = await createAdapterFromUrl(url, resolvedUser, resolvedPassword);
1223
- return new Database(setAdapter(adapter));
1239
+ return exposeDb(new Database(setAdapter(adapter)));
1224
1240
  }
1225
1241
 
1226
1242
  // Legacy config path — normalize "sqlserver" to "mssql"
@@ -1245,7 +1261,7 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1245
1261
  case "sqlite": {
1246
1262
  const { SQLiteAdapter } = await import("./adapters/sqlite.js");
1247
1263
  const adapter = new SQLiteAdapter(config?.path ?? "./data/tina4.db");
1248
- return new Database(setAdapter(adapter));
1264
+ return exposeDb(new Database(setAdapter(adapter)));
1249
1265
  }
1250
1266
  case "postgres": {
1251
1267
  const { PostgresAdapter } = await import("./adapters/postgres.js");
@@ -1257,7 +1273,7 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1257
1273
  database: config?.database,
1258
1274
  });
1259
1275
  await adapter.connect();
1260
- return new Database(setAdapter(adapter));
1276
+ return exposeDb(new Database(setAdapter(adapter)));
1261
1277
  }
1262
1278
  case "mysql": {
1263
1279
  const { MysqlAdapter } = await import("./adapters/mysql.js");
@@ -1269,7 +1285,7 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1269
1285
  database: config?.database,
1270
1286
  });
1271
1287
  await adapter.connect();
1272
- return new Database(setAdapter(adapter));
1288
+ return exposeDb(new Database(setAdapter(adapter)));
1273
1289
  }
1274
1290
  case "mssql": {
1275
1291
  const { MssqlAdapter } = await import("./adapters/mssql.js");
@@ -1281,7 +1297,7 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1281
1297
  database: config?.database,
1282
1298
  });
1283
1299
  await adapter.connect();
1284
- return new Database(setAdapter(adapter));
1300
+ return exposeDb(new Database(setAdapter(adapter)));
1285
1301
  }
1286
1302
  case "firebird": {
1287
1303
  const { FirebirdAdapter } = await import("./adapters/firebird.js");
@@ -1293,7 +1309,7 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1293
1309
  database: config?.database,
1294
1310
  });
1295
1311
  await adapter.connect();
1296
- return new Database(setAdapter(adapter));
1312
+ return exposeDb(new Database(setAdapter(adapter)));
1297
1313
  }
1298
1314
  case "mongodb": {
1299
1315
  const { MongodbAdapter } = await import("./adapters/mongodb.js");
@@ -1306,14 +1322,14 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
1306
1322
  const connectionString = `mongodb://${creds}${host}:${port}/${database}`;
1307
1323
  const adapter = new MongodbAdapter(connectionString);
1308
1324
  await adapter.connect();
1309
- return new Database(setAdapter(adapter));
1325
+ return exposeDb(new Database(setAdapter(adapter)));
1310
1326
  }
1311
1327
  case "odbc": {
1312
1328
  const { OdbcAdapter } = await import("./adapters/odbc.js");
1313
1329
  const connStr = config?.connectionString ?? config?.url?.replace(/^odbc:\/\/\//, "") ?? "";
1314
1330
  const adapter = new OdbcAdapter({ connectionString: connStr });
1315
1331
  await adapter.connect();
1316
- return new Database(setAdapter(adapter));
1332
+ return exposeDb(new Database(setAdapter(adapter)));
1317
1333
  }
1318
1334
  default:
1319
1335
  throw new Error(`Unknown database type: ${type}`);