tina4-nodejs 3.13.11 → 3.13.12

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/CLAUDE.md CHANGED
@@ -1,10 +1,10 @@
1
- # CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.13.11)
1
+ # CLAUDE.md — AI Developer Guide for tina4-nodejs (v3.13.12)
2
2
 
3
3
  > This file helps AI assistants (Claude, Copilot, Cursor, etc.) understand and work on this codebase effectively.
4
4
 
5
5
  ## What This Project Is
6
6
 
7
- Tina4 for Node.js/TypeScript v3.13.11 — The Intelligent Native Application 4ramework. A convention-over-configuration structural paradigm. The developer writes TypeScript; Tina4 is invisible infrastructure.
7
+ Tina4 for Node.js/TypeScript v3.13.12 — The Intelligent Native Application 4ramework. A convention-over-configuration structural paradigm. The developer writes TypeScript; Tina4 is invisible infrastructure.
8
8
 
9
9
  The philosophy: zero ceremony, batteries included, file system as source of truth.
10
10
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- "version": "3.13.11",
6
+ "version": "3.13.12",
7
7
 
8
8
  "type": "module",
9
9
  "description": "Tina4 for Node.js/TypeScript \u2014 54 built-in features, zero dependencies",
@@ -2,6 +2,26 @@ import { AsyncLocalStorage } from "node:async_hooks";
2
2
  import type { DatabaseAdapter, DatabaseResult as DatabaseWriteResult } from "./types.js";
3
3
  import { DatabaseResult } from "./databaseResult.js";
4
4
 
5
+ /**
6
+ * v3.13.12 — strip trailing `;` and whitespace from user-supplied SQL
7
+ * before the framework wraps it with COUNT(*) subqueries or appends
8
+ * LIMIT/OFFSET clauses. Without this, `"SELECT * FROM t;"` becomes
9
+ * `"SELECT * FROM t; LIMIT 100 OFFSET 0"` — a syntax error on every
10
+ * engine. Internal semicolons (in string literals, between meaningful
11
+ * statements) are left alone; drivers reject those if the engine
12
+ * doesn't support multi-statement.
13
+ *
14
+ * Exported so adapters and external tooling can compose it.
15
+ */
16
+ export function stripTrailingSemicolons(sql: string): string {
17
+ if (!sql) return sql;
18
+ let stripped = sql.replace(/\s+$/, "");
19
+ while (stripped.endsWith(";")) {
20
+ stripped = stripped.slice(0, -1).replace(/\s+$/, "");
21
+ }
22
+ return stripped;
23
+ }
24
+
5
25
  let activeAdapter: DatabaseAdapter | null = null;
6
26
  const namedAdapters: Map<string, DatabaseAdapter> = new Map();
7
27
 
@@ -404,6 +424,10 @@ export class Database {
404
424
 
405
425
  /** Query rows with optional pagination. Returns a DatabaseResult wrapper. */
406
426
  fetch(sql: string, params?: unknown[], limit?: number, offset?: number): DatabaseResult {
427
+ // v3.13.12: strip trailing `;` before the adapter wraps with COUNT(*)
428
+ // or appends LIMIT/OFFSET. Without this, `"SELECT * FROM t;"` becomes
429
+ // `"SELECT * FROM t; LIMIT 100 OFFSET 0"` — a syntax error.
430
+ sql = stripTrailingSemicolons(sql);
407
431
  const adapter = this.getNextAdapter();
408
432
  const rows = adapter.fetch<Record<string, unknown>>(sql, params, limit, offset);
409
433
  return new DatabaseResult(rows, undefined, undefined, limit, offset, adapter, sql);
@@ -411,6 +435,7 @@ export class Database {
411
435
 
412
436
  /** Fetch a single row or null. */
413
437
  fetchOne<T = Record<string, unknown>>(sql: string, params?: unknown[]): T | null {
438
+ sql = stripTrailingSemicolons(sql);
414
439
  return this.getNextAdapter().fetchOne<T>(sql, params);
415
440
  }
416
441
 
@@ -14,7 +14,7 @@ export { FetchResult } from "./types.js";
14
14
 
15
15
  export { DatabaseResult } from "./databaseResult.js";
16
16
  export type { ColumnInfoResult } from "./databaseResult.js";
17
- export { Database, initDatabase, getAdapter, setAdapter, closeDatabase, parseDatabaseUrl, setNamedAdapter, getNamedAdapter, resolveDbPool } from "./database.js";
17
+ export { Database, initDatabase, getAdapter, setAdapter, closeDatabase, parseDatabaseUrl, setNamedAdapter, getNamedAdapter, resolveDbPool, stripTrailingSemicolons } from "./database.js";
18
18
  export type { DatabaseConfig, ParsedDatabaseUrl } from "./database.js";
19
19
  export { discoverModels } from "./model.js";
20
20
  export type { DiscoveredModel } from "./model.js";