tina4-nodejs 3.12.10 → 3.13.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.
@@ -414,6 +414,23 @@ export class Database {
414
414
  return this.getNextAdapter().fetchOne<T>(sql, params);
415
415
  }
416
416
 
417
+ /**
418
+ * Fetch rows and return the records array directly.
419
+ *
420
+ * Symmetric with `fetchOne`. For the common case where you just want
421
+ * the rows and don't need the `DatabaseResult` metadata, this is one
422
+ * less attribute access than `fetch(...).records`.
423
+ *
424
+ * const rows = db.fetchAll("SELECT * FROM users WHERE active = ?", [true]);
425
+ * for (const row of rows) console.log(row.name);
426
+ *
427
+ * Returns `[]` (not `null`) when no rows match. Cross-framework parity
428
+ * with Python `db.fetch_all()`, PHP `$db->fetchAll()`, and Ruby `db.fetch_all`.
429
+ */
430
+ fetchAll<T = Record<string, unknown>>(sql: string, params?: unknown[], limit?: number, offset?: number): T[] {
431
+ return this.fetch(sql, params, limit, offset).records as T[];
432
+ }
433
+
417
434
  /**
418
435
  * Execute a write statement. Returns true/false for simple writes.
419
436
  * If SQL contains RETURNING, CALL, EXEC, or SELECT, returns the result set.
@@ -845,6 +862,37 @@ export function resolveDbPool(): number {
845
862
  return isNaN(n) || n < 0 ? 0 : n;
846
863
  }
847
864
 
865
+ /**
866
+ * Open a database connection — convention name matching SQLAlchemy
867
+ * `engine.connect()` and the cross-framework Database.get_connection()
868
+ * surface shipped in 3.13.x.
869
+ *
870
+ * Equivalent to `initDatabase({ url })` but with an opinionated, simpler
871
+ * signature: pass a URL string directly, or omit for env-based defaults
872
+ * (falls back to in-memory SQLite when nothing resolves).
873
+ *
874
+ * const db = await Database.getConnection(); // from env
875
+ * const db = await Database.getConnection("sqlite://./app.db"); // explicit URL
876
+ * const db = await Database.getConnection("postgres://localhost/x", { username: "u", password: "p" });
877
+ *
878
+ * Cross-framework parity with Python `Database.get_connection()`, PHP
879
+ * `\Tina4\Database::getConnection()`, and Ruby `Tina4::Database.get_connection`.
880
+ */
881
+ // eslint-disable-next-line @typescript-eslint/no-namespace
882
+ export namespace Database {
883
+ export async function getConnection(
884
+ url?: string,
885
+ opts: { username?: string; password?: string } = {}
886
+ ): Promise<Database> {
887
+ const resolvedUrl = url ?? process.env.TINA4_DATABASE_URL ?? "sqlite::memory:";
888
+ return initDatabase({
889
+ url: resolvedUrl,
890
+ username: opts.username,
891
+ password: opts.password,
892
+ });
893
+ }
894
+ }
895
+
848
896
  export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
849
897
  // Resolve credentials: config.user > config.username > env TINA4_DATABASE_USERNAME
850
898
  const resolvedUser = config?.user ?? config?.username ?? process.env.TINA4_DATABASE_USERNAME;
@@ -869,6 +917,20 @@ export async function initDatabase(config?: DatabaseConfig): Promise<Database> {
869
917
  const rawType = config?.type ?? "sqlite";
870
918
  const type = rawType === "sqlserver" ? "mssql" : rawType;
871
919
 
920
+ // Loud warning when we hit the default SQLite path because nothing was
921
+ // configured. Silent fallback was the cause of "my migrations went to the
922
+ // wrong DB" — the developer thought their .env was being honoured.
923
+ // Only warn when the caller passed no config AND no env var was set; an
924
+ // explicit `{ type: "sqlite" }` call is intentional and stays silent.
925
+ if (config === undefined && !process.env.TINA4_DATABASE_URL) {
926
+ const path = "./data/tina4.db";
927
+ console.warn(
928
+ `[tina4] No TINA4_DATABASE_URL set — falling back to SQLite at ${path}. ` +
929
+ `If you meant to use Postgres/MySQL/etc., set TINA4_DATABASE_URL in your .env ` +
930
+ `and re-run. (Was the .env loaded? CLI commands must call loadEnv() first.)`,
931
+ );
932
+ }
933
+
872
934
  switch (type) {
873
935
  case "sqlite": {
874
936
  const { SQLiteAdapter } = await import("./adapters/sqlite.js");