turbine-orm 0.28.1 → 0.28.3

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/README.md CHANGED
@@ -14,7 +14,7 @@ Every TS ORM now resolves nested relations in a single `json_agg` query — Pris
14
14
 
15
15
  1. **Read-only Studio your DBA will approve.** `npx turbine studio` spins up a loopback-bound web UI with 192-bit auth tokens, `BEGIN READ ONLY` transactions, and — since v0.19 — no raw-SQL surface at all: queries are composed in the ORM's own validated builder. The only TS ORM Studio that physically cannot mutate your database.
16
16
  2. **PII-safe error messages.** Turbine errors show WHERE keys, not values. A `UniqueConstraintError` says which column violated the constraint — never the actual user data. Safe to log, safe to surface to monitoring, no scrubbing needed.
17
- 3. **One runtime dependency (`pg`).** No engine binary, no WASM, no adapter packages to keep in lockstep. The main entry bundles to ~42 kB brotli; the edge entry to ~33 kB brotli. Prisma 7 dropped its Rust query engine, but its client still ships a TypeScript/WASM query compiler — a ~1.6 MB bundle, down from the ~14 MB Rust-era client.
17
+ 3. **One runtime dependency (`pg`).** No engine binary, no WASM, no adapter packages to keep in lockstep. The main entry's **import graph** is ~42 kB brotli (edge ~33 kB) with `pg` external — that is the client footprint your bundler sees, not the dual ESM+CJS install size on disk (~3 MB). Prisma 7 dropped its Rust query engine, but its client still ships a TypeScript/WASM query compiler — a ~1.6 MB bundle, down from the ~14 MB Rust-era client.
18
18
  4. **SQL-first migrations with drift detection.** Write real SQL. SHA-256 checksums catch modified migration files. `pg_try_advisory_lock()` prevents concurrent runs. Each migration in its own transaction. No shadow database, no magic DSL.
19
19
  5. **Edge-native — one import swap.** `turbineHttp(pool, SCHEMA)` — same API on Neon, Vercel Postgres, Cloudflare Hyperdrive, Supabase. No WASM bundle, no adapter package, no separate serverless build.
20
20
  6. **Pipeline batching via wire protocol.** Real Parse/Bind/Execute pipeline — not queries wrapped in a transaction. N independent queries in one round-trip.
@@ -882,7 +882,7 @@ Everything is honest about what ports and what doesn't. Features marked **PG-onl
882
882
 
883
883
  **Engine notes:** SQLite uses `RETURNING` (≥ 3.35) just like Postgres. MySQL has no `RETURNING`, so writes re-`SELECT` the affected row and **`createMany` returns `[]`** (the rows ARE inserted — re-query if you need them). SQL Server returns rows via `OUTPUT`/`MERGE`; `DISTINCT ON` is Postgres-only. Only Postgres streams via a true cursor (constant memory); the other engines' `findManyStream` materializes the result then yields it in batches. Optimistic locking throws `OptimisticLockError` on all engines (on MySQL the conflict is detected from the version-checked UPDATE's affected-row count). The `turbine` CLI (`generate`, `migrate`) is currently PostgreSQL-only — point the engine factories at a hand-written or programmatically introspected `SCHEMA`.
884
884
 
885
- **PowDB** speaks its own non-SQL query language (PowQL), so it sits outside the SQL matrix above. It uses `reselect` writes with client-assigned UUID PKs, N+1 relation loaders (no `json_agg`), single-writer transactions (no nesting), and `defineSchema` (no introspection). Embedded `syncMode: 'normal'` writes beat SQLite; the networked transport runs the same data over a socket. many-to-many, nested writes, composite keys, cursor streaming, and the Postgres-only trio throw `UnsupportedFeatureError`. Full details: **[turbineorm.dev/engines#powdb](https://turbineorm.dev/engines#powdb)**.
885
+ **PowDB** speaks its own non-SQL query language (PowQL), so it sits outside the SQL matrix above. Writes use a trailing **`returning`** keyword (upsert reselects by PK). PKs are server-assigned `auto` ints **or** client UUIDs. Nested relations load client-side (N+1, including many-to-many via the junction — no `json_agg`). Nested writes cover hasMany/hasOne/belongsTo; many-to-many nested writes are not supported. Transactions are single-writer (no nested savepoints). Schema is code-first via `defineSchema` (no wire introspection). Embedded `syncMode: 'normal'` moves fsync off the commit path; the networked transport runs the same data over a socket. Cursor streaming and the Postgres-only trio (pgvector / LISTEN/NOTIFY / RLS session GUCs) throw `UnsupportedFeatureError`. Full details: **[turbineorm.dev/engines#powdb](https://turbineorm.dev/engines#powdb)**.
886
886
 
887
887
  Full setup, signatures, and the complete support matrix: **[turbineorm.dev/engines](https://turbineorm.dev/engines)**.
888
888
 
@@ -523,7 +523,7 @@ function generateIndex(schema) {
523
523
  const lines = [
524
524
  ...generatedFileHeader(),
525
525
  "import { TurbineClient as BaseTurbineClient, TransactionClient as BaseTransactionClient, QueryInterface } from 'turbine-orm';",
526
- "import type { TurbineConfig, TransactionOptions } from 'turbine-orm';",
526
+ "import type { TurbineConfig, TransactionOptions, DeferredQuery, PipelineResults } from 'turbine-orm';",
527
527
  "import { SCHEMA } from './metadata.js';",
528
528
  ];
529
529
  // Import all entity types and relations maps
@@ -607,9 +607,13 @@ function generateIndex(schema) {
607
607
  lines.push('');
608
608
  // Augment TurbineClient via interface merging with a typed $transaction
609
609
  // overload. The callback parameter is narrowed to `TypedTransactionClient`
610
- // so users get autocomplete on `tx.users`, `tx.posts`, etc. The base
611
- // signature (callback parameter `BaseTransactionClient`) remains valid as
612
- // an overload, so prior usage continues to typecheck.
610
+ // so users get autocomplete on `tx.users`, `tx.posts`, etc.
611
+ //
612
+ // IMPORTANT: the merged member must be compatible with the base class's
613
+ // $transaction ON ITS OWN (TS2415) — since v0.26 the base method also has a
614
+ // batch-array overload (`$transaction([...queries])`), so the merged
615
+ // interface must redeclare BOTH signatures. Emitting only the callback form
616
+ // makes every generated client fail `tsc` with "incorrectly extends".
613
617
  lines.push('export interface TurbineClient {');
614
618
  lines.push(' /**');
615
619
  lines.push(' * Run a callback inside a transaction. The callback receives a typed');
@@ -619,6 +623,13 @@ function generateIndex(schema) {
619
623
  lines.push(' fn: (tx: TypedTransactionClient) => Promise<R>,');
620
624
  lines.push(' options?: TransactionOptions,');
621
625
  lines.push(' ): Promise<R>;');
626
+ lines.push(' /**');
627
+ lines.push(' * Batch form: run several deferred queries in one transaction and get');
628
+ lines.push(' * their results as a tuple (same as the base client).');
629
+ lines.push(' */');
630
+ lines.push(' $transaction<T extends readonly DeferredQuery<unknown>[]>(');
631
+ lines.push(' queries: readonly [...T],');
632
+ lines.push(' ): Promise<PipelineResults<T>>;');
622
633
  lines.push('}');
623
634
  lines.push('');
624
635
  // Factory function with JSDoc
package/dist/generate.js CHANGED
@@ -516,7 +516,7 @@ export function generateIndex(schema) {
516
516
  const lines = [
517
517
  ...generatedFileHeader(),
518
518
  "import { TurbineClient as BaseTurbineClient, TransactionClient as BaseTransactionClient, QueryInterface } from 'turbine-orm';",
519
- "import type { TurbineConfig, TransactionOptions } from 'turbine-orm';",
519
+ "import type { TurbineConfig, TransactionOptions, DeferredQuery, PipelineResults } from 'turbine-orm';",
520
520
  "import { SCHEMA } from './metadata.js';",
521
521
  ];
522
522
  // Import all entity types and relations maps
@@ -600,9 +600,13 @@ export function generateIndex(schema) {
600
600
  lines.push('');
601
601
  // Augment TurbineClient via interface merging with a typed $transaction
602
602
  // overload. The callback parameter is narrowed to `TypedTransactionClient`
603
- // so users get autocomplete on `tx.users`, `tx.posts`, etc. The base
604
- // signature (callback parameter `BaseTransactionClient`) remains valid as
605
- // an overload, so prior usage continues to typecheck.
603
+ // so users get autocomplete on `tx.users`, `tx.posts`, etc.
604
+ //
605
+ // IMPORTANT: the merged member must be compatible with the base class's
606
+ // $transaction ON ITS OWN (TS2415) — since v0.26 the base method also has a
607
+ // batch-array overload (`$transaction([...queries])`), so the merged
608
+ // interface must redeclare BOTH signatures. Emitting only the callback form
609
+ // makes every generated client fail `tsc` with "incorrectly extends".
606
610
  lines.push('export interface TurbineClient {');
607
611
  lines.push(' /**');
608
612
  lines.push(' * Run a callback inside a transaction. The callback receives a typed');
@@ -612,6 +616,13 @@ export function generateIndex(schema) {
612
616
  lines.push(' fn: (tx: TypedTransactionClient) => Promise<R>,');
613
617
  lines.push(' options?: TransactionOptions,');
614
618
  lines.push(' ): Promise<R>;');
619
+ lines.push(' /**');
620
+ lines.push(' * Batch form: run several deferred queries in one transaction and get');
621
+ lines.push(' * their results as a tuple (same as the base client).');
622
+ lines.push(' */');
623
+ lines.push(' $transaction<T extends readonly DeferredQuery<unknown>[]>(');
624
+ lines.push(' queries: readonly [...T],');
625
+ lines.push(' ): Promise<PipelineResults<T>>;');
615
626
  lines.push('}');
616
627
  lines.push('');
617
628
  // Factory function with JSDoc
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turbine-orm",
3
- "version": "0.28.1",
3
+ "version": "0.28.3",
4
4
  "description": "Postgres-native TypeScript ORM — runs on Neon, Vercel Postgres, Cloudflare, Supabase. Streaming cursors, typed errors, single-query nested relations. One dependency, no WASM engine",
5
5
  "type": "module",
6
6
  "exports": {
@@ -94,10 +94,10 @@
94
94
  "node": ">=20.0.0"
95
95
  },
96
96
  "dependencies": {
97
+ "@types/pg": "^8.11.11",
97
98
  "pg": "^8.13.1"
98
99
  },
99
100
  "devDependencies": {
100
- "@types/pg": "^8.11.11",
101
101
  "@biomejs/biome": "^2.4.10",
102
102
  "@size-limit/esbuild": "^12.1.0",
103
103
  "@size-limit/file": "^12.1.0",