turbine-orm 0.7.1 → 0.8.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.
package/README.md CHANGED
@@ -8,34 +8,35 @@ npm install turbine-orm
8
8
 
9
9
  ## Why Turbine?
10
10
 
11
- Turbine is a PostgreSQL-native TypeScript ORM with features no other ORM offers together: **cursor-based streaming** through nested relations, **typed error classes** with PostgreSQL constraint mapping, **pipeline batching** (N queries, 1 round-trip), **middleware**, and a driver-agnostic core that plugs into any pg-compatible pool so it runs on Vercel Edge, Cloudflare Workers, Deno Deploy, and similar environments. It resolves nested relations in a single SQL query using `json_agg` — an approach now shared by Prisma 7+ and Drizzle v2, but Turbine does it with 1 runtime dependency (`pg`) and ~110KB on npm.
11
+ Turbine is a PostgreSQL-native TypeScript ORM with features no other ORM offers together: **deep typed `with` inference** (`users[0].posts[0].comments[0].author` autocompletes after one `findMany`), **cursor-based streaming** through nested relations, **typed error classes** with PostgreSQL constraint mapping, **pipeline batching** (N queries, 1 round-trip), **middleware**, and a driver-agnostic core that plugs into any pg-compatible pool so it runs on Vercel Edge, Cloudflare Workers, Deno Deploy, and similar environments. 1 runtime dependency (`pg`), ~110KB on npm.
12
12
 
13
- **One query for nested relations.** When you write `db.users.findMany({ with: { posts: { with: { comments: true } } } })`, Turbine generates a single SQL statement using correlated subqueries with `json_agg`. Modern ORMs like Prisma 7+ and Drizzle v2 use similar single-query approaches (LATERAL JOINs). Turbine's advantage is architectural simplicity: 1 dependency, no code generation DSL, and PostgreSQL-native depth.
13
+ **One round-trip for nested relations.** `db.users.findMany({ with: { posts: { with: { comments: true } } } })` resolves the entire object graph in a single database round-trip, regardless of nesting depth. Prisma 7+ and Drizzle v2 also do single-query nested loads Turbine's advantage is architectural simplicity: 1 dependency, no code generation DSL, no query plan compiler.
14
14
 
15
15
  ## Benchmarks
16
16
 
17
- Tested against **Prisma 7.6** (adapter-pg, relationJoins) and **Drizzle 0.45** (relational queries) on the same PostgreSQL database. 200 iterations, 20 warmup, Node v22.
17
+ Tested against **Prisma 7.6** (adapter-pg, relationJoins preview on) and **Drizzle 0.45** (relational queries) on a **Neon** PostgreSQL database (pooled endpoint, US-East, PostgreSQL 17.8). 100 iterations, 20 warmup, Node v22. Same schema, same data (1K users, 10K posts, 50K comments), same connection pool config.
18
18
 
19
19
  | Scenario | Turbine | Prisma 7 | Drizzle v2 |
20
20
  |---|---|---|---|
21
- | **findMany — 100 rows (flat)** | **0.39 ms** | 0.58 ms | 0.44 ms |
22
- | **findMany — L2 nested (users + posts)** | **1.29 ms** | 1.84 ms | 1.30 ms |
23
- | **findMany — L3 nested (users → posts → comments)** | **0.50 ms** | 0.91 ms | 0.69 ms |
24
- | **findUnique by PK** | **0.08 ms** | 0.13 ms | 0.14 ms |
25
- | **findUnique — L3 nested** | **0.18 ms** | 0.32 ms | 0.34 ms |
26
- | **count** | **0.06 ms** | 0.10 ms | 0.08 ms |
21
+ | findMany — 100 users (flat) | **51.97 ms** | 52.90 ms | 53.51 ms |
22
+ | findMany — 50 users + posts (L2) | **55.84 ms** | 56.10 ms | 88.80 ms |
23
+ | findMany — 10 users → posts → comments (L3) | 52.77 ms | 59.35 ms | **52.38 ms** |
24
+ | findUnique — single user by PK | **47.66 ms** | 52.15 ms | 47.78 ms |
25
+ | findUnique — user + posts + comments (L3) | **51.71 ms** | 54.42 ms | 52.47 ms |
26
+ | count — all users | **44.57 ms** | 47.54 ms | 46.75 ms |
27
+ | stream — iterate 50K rows (batch 1000) | 3,207 ms | **3,099 ms** | 4,620 ms |
28
+ | atomic increment — `view_count + 1` | 49.76 ms | 49.09 ms | **46.25 ms** |
29
+ | pipeline — 5-query batch | 318 ms | 327 ms | **316 ms** |
27
30
 
28
- | Scenario | Turbine | Prisma 7 | Drizzle v2 |
29
- |---|---|---|---|
30
- | findMany — flat | **1.00x** | 1.51x | 1.15x |
31
- | findMany — L2 nested | **1.00x** | 1.43x | 1.01x |
32
- | findMany — L3 nested | **1.00x** | 1.81x | 1.38x |
33
- | findUnique by PK | **1.00x** | 1.67x | 1.69x |
34
- | findUnique — L3 nested | **1.00x** | 1.81x | 1.93x |
35
- | count | **1.00x** | 1.70x | 1.38x |
31
+ **Against a real pooled database, most single-query scenarios are within noise** — network round-trip to Neon is ~33–40 ms, which swamps per-query CPU overhead. But a few results stand out:
36
32
 
37
- Turbine is fastest in every scenario. The advantage is largest on deep nesting (1.8x vs Prisma, up to 1.9x vs Drizzle) and single-record lookups (1.7x). All three ORMs now use single-query approaches for nested relations — Turbine's advantage comes from lower per-query overhead (minimal JS object allocation, no query plan compilation layer, direct pg driver access).
33
+ - **L2 nested reads.** Turbine and Prisma are neck-and-neck (~56 ms), while Drizzle is **1.59× slower** (89 ms) on the 50-user + posts scenario. Turbine's `json_agg` approach and SQL template caching pay off here.
34
+ - **Streaming 50K rows.** Turbine's optimized streaming (speculative first fetch + batch size 1000) matches Prisma at ~3.1–3.2 s. Drizzle's keyset pagination is 1.49× slower at 4.6 s. Turbine's cursor still gives you correctness on any `orderBy` and clean early-`break` semantics.
35
+ - **Pipeline batching** puts 5 independent queries through a single round-trip using the Postgres extended-query pipeline protocol — all three ORMs are tied here since each runs 5 queries sequentially in a transaction.
38
36
 
37
+ Beyond the numbers, Turbine's real strengths are: **one runtime dependency** (`pg`, ~110 KB), a **single import swap** for edge runtimes (`turbine-orm/serverless`), **typed Postgres errors** with a `readonly isRetryable` const for retry loops, and **inferred `with` result types** — `users[0].posts[0].comments[0].author.name` autocompletes from a single `findMany` with no manual assertion.
38
+
39
+ > Full analysis with p50/p95/p99 and methodology notes: [`benchmarks/RESULTS.md`](./benchmarks/RESULTS.md).
39
40
  > Reproduce: `cd benchmarks && npm install && npx prisma generate && DATABASE_URL=... npx tsx bench.ts`
40
41
 
41
42
  ## Quick Start
@@ -223,7 +224,7 @@ const users = await db.users.findMany({
223
224
  // Stream rows using PostgreSQL cursors — constant memory, no matter how many rows
224
225
  for await (const user of db.users.findManyStream({
225
226
  where: { orgId: 1 },
226
- batchSize: 500, // internal FETCH batch size (default: 100)
227
+ batchSize: 500, // internal FETCH batch size (default: 1000)
227
228
  orderBy: { id: 'asc' },
228
229
  with: { posts: true }, // nested relations work too
229
230
  })) {
@@ -295,7 +296,7 @@ try {
295
296
  }
296
297
  ```
297
298
 
298
- Error codes: `TURBINE_E001` (NotFound), `TURBINE_E002` (Timeout), `TURBINE_E003` (Validation), `TURBINE_E004` (Connection), `TURBINE_E005` (Relation), `TURBINE_E006` (Migration), `TURBINE_E007` (CircularRelation).
299
+ Error codes: `TURBINE_E001` (NotFound), `TURBINE_E002` (Timeout), `TURBINE_E003` (Validation), `TURBINE_E004` (Connection), `TURBINE_E005` (Relation), `TURBINE_E006` (Migration), `TURBINE_E007` (CircularRelation), `TURBINE_E008` (UniqueConstraint), `TURBINE_E009` (ForeignKey), `TURBINE_E010` (NotNullViolation), `TURBINE_E011` (CheckConstraint), `TURBINE_E012` (Deadlock), `TURBINE_E013` (SerializationFailure), `TURBINE_E014` (Pipeline).
299
300
 
300
301
  ## WHERE Operator Reference
301
302
 
@@ -532,22 +533,9 @@ Priority order: CLI flags > environment variables (`DATABASE_URL`) > config file
532
533
 
533
534
  ## How It Works
534
535
 
535
- Turbine generates a single SQL query using Postgres `json_agg` + subqueries to fetch nested relations:
536
-
537
- ```sql
538
- -- db.users.findMany({ where: { orgId: 1 }, with: { posts: { with: { comments: true } } } })
539
- SELECT u.*,
540
- (SELECT COALESCE(json_agg(sub), '[]'::json) FROM (
541
- SELECT p.*,
542
- (SELECT COALESCE(json_agg(sub2), '[]'::json) FROM (
543
- SELECT c.* FROM comments c WHERE c.post_id = p.id
544
- ) sub2) AS comments
545
- FROM posts p WHERE p.user_id = u.id
546
- ) sub) AS posts
547
- FROM users u WHERE u.org_id = 1
548
- ```
536
+ Turbine resolves the entire object graph in a single database round-trip, regardless of nesting depth. The `with` clause is fully type-inferred end-to-end `users[0].posts[0].comments[0].author.name` autocompletes from a single `findMany` call, with no manual type assertions.
549
537
 
550
- This resolves the entire 3-level object graph in one database round-trip. Prisma 7+ and Drizzle v2 also use single-query approaches (LATERAL JOINs), but Turbine's correlated subquery strategy has lower per-query overhead see [Benchmarks](#benchmarks).
538
+ Prisma 7+ and Drizzle v2 also do single-query nested loads. Turbine's advantage isn't query latency (see [Benchmarks](#benchmarks) — all three are within noise over a real pooled database); it's architectural simplicity. One runtime dependency (`pg`), no DSL compiler, no driver adapter shim for edge, and deep `with` type inference without verbose helper types.
551
539
 
552
540
  ## Type Mapping
553
541
 
@@ -569,26 +557,34 @@ Turbine maps Postgres types to TypeScript:
569
557
 
570
558
  | | **Turbine** | **Prisma** | **Drizzle** | **Kysely** |
571
559
  |---|---|---|---|---|
572
- | **Nested relations** | 1 query (`json_agg`) | 1 query (LATERAL JOIN + json_agg, since v5.8) | 1 query (LATERAL JOINs) | Manual (`jsonArrayFrom`) |
560
+ | **Nested relations** | 1 query, deep type inference | 1 query (since v5.8), shallow inference | 1 query, requires `relations()` re-declaration | Manual (`jsonArrayFrom`) |
573
561
  | **API style** | `findMany`, `with` | `findMany`, `include` | SQL-like + relational | SQL builder |
574
562
  | **Schema** | TypeScript | Custom DSL (`.prisma`) | TypeScript | Manual interfaces |
575
563
  | **Runtime deps** | 1 (`pg`) | `@prisma/client` + adapter | 0 | 0 |
576
564
  | **Multi-DB** | PostgreSQL only | PG, MySQL, SQLite, MSSQL | PG, MySQL, SQLite | PG, MySQL, SQLite |
577
565
  | **Code generation** | `turbine generate` | `prisma generate` | Not needed | Not needed |
578
566
 
579
- All three ORMs now use single-query approaches for nested relations. Turbine uses correlated subqueries with `json_agg`, Prisma 7 uses LATERAL JOIN + `json_agg`, and Drizzle uses LATERAL JOINs. Turbine is 1.4–1.9x faster due to lower per-query overhead minimal JS object allocation, no query plan compilation layer, and direct pg driver access. See [Benchmarks](#benchmarks) for full results.
567
+ All three ORMs now do single-query nested loads. Over a real pooled database (Neon, US-East) most single-query scenarios land within noise — but Turbine's SQL template caching and prepared statements give it a consistent edge, particularly on L2 nested reads (1.59× faster than Drizzle) and streaming (at parity with Prisma, 1.49× faster than Drizzle). Turbine's differentiators are both architectural and performance: one runtime dependency, one import swap for edge, typed errors with `isRetryable`, deep `with` type inference, and real Postgres pipeline protocol support. See [Benchmarks](#benchmarks) and [`benchmarks/RESULTS.md`](./benchmarks/RESULTS.md) for the full breakdown.
580
568
 
581
569
  ## Limitations
582
570
 
583
571
  Turbine is focused and opinionated. Here's what it doesn't do:
584
572
 
585
- - **PostgreSQL only.** No MySQL, SQLite, or MSSQL. This is by design — the `json_agg` approach is PostgreSQL-specific, and going deep on one database enables the performance advantage.
573
+ - **PostgreSQL only.** No MySQL, SQLite, or MSSQL. By design — going deep on one database enables the performance advantage and the edge-runtime story.
586
574
  - **No full-text search operators.** TSVECTOR/TSQUERY are not exposed in the query builder. Use `db.raw` for full-text queries.
587
- - **Large nested result sets.** `json_agg` builds the entire JSON array in PostgreSQL memory. For relations with 10K+ rows, always use `limit` in your `with` clause to cap the aggregation size.
575
+ - **Large nested result sets.** Nested results are materialized server-side in PostgreSQL memory. For relations with 10K+ rows, always use `limit` in your `with` clause or stream the parents with `findManyStream` and resolve children per-row.
588
576
  - **No admin UI.** Turbine Studio is planned but not yet available.
589
577
 
590
578
  ## Examples
591
579
 
580
+ **Feature demos**
581
+
582
+ - **[Thread Machine](./examples/thread-machine/)** — HN clone rendered from a single `findMany`. 4-level object graph (stories → comments → replies → author), every property autocompletes through the chain
583
+ - **[Streaming CSV](./examples/streaming-csv/)** — Export 100K orders + line items to CSV with constant memory. PostgreSQL cursors, live heap meter, nested `with` inside `findManyStream`
584
+ - **[Clickstorm](./examples/clickstorm/)** — Side-by-side atomic-increment vs read-modify-write load test. 10K concurrent clicks. The atomic path wins every time
585
+
586
+ **Runtime targets**
587
+
592
588
  - **[Next.js](./examples/nextjs/)** — Server-rendered app with nested relations, streaming, and live code demos
593
589
  - **[Neon Edge](./examples/neon-edge/)** — Vercel Edge route handler talking to Neon over HTTP via `@neondatabase/serverless`
594
590
  - **[Vercel Postgres](./examples/vercel-postgres/)** — Next.js app router route handler on `@vercel/postgres`
@@ -134,9 +134,15 @@ class TransactionClient {
134
134
  // Return a minimal pool-compatible object that routes queries
135
135
  // through the transaction client
136
136
  return {
137
- query: async (text, values) => {
137
+ query: async (textOrConfig, values) => {
138
138
  try {
139
- return await client.query(text, values);
139
+ if (typeof textOrConfig === 'string') {
140
+ return await client.query(textOrConfig, values);
141
+ }
142
+ // Object form for prepared statements: { name, text, values }
143
+ // pg.PoolClient.query accepts QueryConfig but the overloads make TS
144
+ // unhappy with the union, so we cast through unknown.
145
+ return await client.query(textOrConfig);
140
146
  }
141
147
  catch (err) {
142
148
  throw (0, errors_js_1.wrapPgError)(err);
@@ -191,9 +197,13 @@ class TurbineClient {
191
197
  }
192
198
  this.logging = config.logging ?? false;
193
199
  this.schema = schema;
200
+ // Respect env var kill switch
201
+ const envDisablePrepared = typeof process !== 'undefined' && process.env?.TURBINE_DISABLE_PREPARED === '1';
194
202
  this.queryOptions = {
195
203
  defaultLimit: config.defaultLimit,
196
204
  warnOnUnlimited: config.warnOnUnlimited,
205
+ preparedStatements: envDisablePrepared ? false : (config.preparedStatements ?? !config.pool),
206
+ sqlCache: config.sqlCache ?? true,
197
207
  };
198
208
  // Apply NotFoundError message redaction mode (default: safe — values are
199
209
  // stripped from messages to avoid leaking PII into error logs).
@@ -307,13 +317,41 @@ class TurbineClient {
307
317
  /**
308
318
  * Execute multiple queries in a single database round-trip.
309
319
  *
310
- * Pass the result of any `.build*()` method on a table accessor.
320
+ * Two call styles:
321
+ * - `db.pipeline(q1, q2, q3)` — rest params (backward-compatible)
322
+ * - `db.pipeline([q1, q2, q3], { transactional: false })` — array + options
323
+ *
324
+ * On pg.Pool-backed connections with TCP, this uses the real Postgres
325
+ * extended-query pipeline protocol (one TCP flush, one round-trip).
326
+ * On HTTP-based drivers it falls back to sequential execution.
311
327
  */
312
- async pipeline(...queries) {
328
+ async pipeline(...args) {
329
+ let queries;
330
+ let options;
331
+ // Detect which overload was used
332
+ if (args.length > 0 &&
333
+ Array.isArray(args[0]) &&
334
+ args[0].every((item) => item && typeof item === 'object' && 'sql' in item)) {
335
+ // Array form: pipeline([q1, q2], opts?)
336
+ queries = args[0];
337
+ options = args[1];
338
+ }
339
+ else {
340
+ // Rest-param form: pipeline(q1, q2, q3)
341
+ queries = args;
342
+ }
313
343
  if (this.logging) {
314
344
  console.log(`[turbine] Pipeline: ${queries.length} queries — ${queries.map((q) => q.tag).join(', ')}`);
315
345
  }
316
- return (0, pipeline_js_1.executePipeline)(this.pool, queries);
346
+ return (0, pipeline_js_1.executePipeline)(this.pool, queries, options);
347
+ }
348
+ /**
349
+ * Check whether the underlying pool supports the real pipeline protocol.
350
+ * Returns `true` for standard pg.Pool TCP connections, `false` for HTTP
351
+ * drivers (Neon HTTP, Vercel Postgres, etc.) and mock pools.
352
+ */
353
+ async pipelineSupported() {
354
+ return (0, pipeline_js_1.pipelineSupported)(this.pool);
317
355
  }
318
356
  // -------------------------------------------------------------------------
319
357
  // Raw SQL — tagged template literal escape hatch
@@ -6,7 +6,7 @@
6
6
  * All Turbine errors extend TurbineError which includes a `code` property.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.CheckConstraintError = exports.SerializationFailureError = exports.DeadlockError = exports.NotNullViolationError = exports.ForeignKeyError = exports.UniqueConstraintError = exports.CircularRelationError = exports.MigrationError = exports.RelationError = exports.ConnectionError = exports.ValidationError = exports.TimeoutError = exports.NotFoundError = exports.TurbineError = exports.TurbineErrorCode = void 0;
9
+ exports.PipelineError = exports.CheckConstraintError = exports.SerializationFailureError = exports.DeadlockError = exports.NotNullViolationError = exports.ForeignKeyError = exports.UniqueConstraintError = exports.CircularRelationError = exports.MigrationError = exports.RelationError = exports.ConnectionError = exports.ValidationError = exports.TimeoutError = exports.NotFoundError = exports.TurbineError = exports.TurbineErrorCode = void 0;
10
10
  exports.setErrorMessageMode = setErrorMessageMode;
11
11
  exports.getErrorMessageMode = getErrorMessageMode;
12
12
  exports.wrapPgError = wrapPgError;
@@ -25,6 +25,7 @@ exports.TurbineErrorCode = {
25
25
  CHECK_VIOLATION: 'TURBINE_E011',
26
26
  DEADLOCK_DETECTED: 'TURBINE_E012',
27
27
  SERIALIZATION_FAILURE: 'TURBINE_E013',
28
+ PIPELINE: 'TURBINE_E014',
28
29
  };
29
30
  /** Base error class for all Turbine errors */
30
31
  class TurbineError extends Error {
@@ -350,6 +351,47 @@ class CheckConstraintError extends TurbineError {
350
351
  }
351
352
  }
352
353
  exports.CheckConstraintError = CheckConstraintError;
354
+ /**
355
+ * Thrown when a non-transactional pipeline has partial failures.
356
+ *
357
+ * In non-transactional mode (`{ transactional: false }`), each query executes
358
+ * independently. If one or more queries fail, the pipeline rejects with a
359
+ * `PipelineError` that carries per-query results so callers can inspect which
360
+ * succeeded and which failed.
361
+ *
362
+ * ```ts
363
+ * try {
364
+ * await db.pipeline([q1, q2, q3], { transactional: false });
365
+ * } catch (err) {
366
+ * if (err instanceof PipelineError) {
367
+ * for (const slot of err.results) {
368
+ * if (slot.status === 'error') console.error(slot.error);
369
+ * }
370
+ * }
371
+ * }
372
+ * ```
373
+ */
374
+ class PipelineError extends TurbineError {
375
+ /** Per-query results: each slot is either `{status:'ok', value}` or `{status:'error', error}` */
376
+ results;
377
+ /** Zero-based index of the first query that failed */
378
+ failedIndex;
379
+ /** Tag of the first query that failed (from DeferredQuery.tag) */
380
+ failedTag;
381
+ constructor(opts) {
382
+ const { results, failedIndex, failedTag, cause } = opts;
383
+ const failedCount = results.filter((r) => r.status === 'error').length;
384
+ const message = opts.message ??
385
+ `[turbine] Pipeline completed with ${failedCount} error(s) out of ${results.length} queries` +
386
+ (failedTag ? ` (first failure: ${failedTag} at index ${failedIndex})` : '');
387
+ super(exports.TurbineErrorCode.PIPELINE, message, { cause });
388
+ this.name = 'PipelineError';
389
+ this.results = results;
390
+ this.failedIndex = failedIndex;
391
+ this.failedTag = failedTag;
392
+ }
393
+ }
394
+ exports.PipelineError = PipelineError;
353
395
  /**
354
396
  * Parse column names out of a pg `detail` string like:
355
397
  * "Key (email)=(foo@bar) already exists."
package/dist/cjs/index.js CHANGED
@@ -34,7 +34,7 @@
34
34
  * ```
35
35
  */
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.turbineHttp = exports.schemaToSQLString = exports.schemaToSQL = exports.schemaPush = exports.schemaDiff = exports.table = exports.defineSchema = exports.column = exports.ColumnBuilder = exports.snakeToPascal = exports.snakeToCamel = exports.singularize = exports.pgTypeToTs = exports.pgArrayType = exports.isDateType = exports.camelToSnake = exports.QueryInterface = exports.executePipeline = exports.introspect = exports.generate = exports.wrapPgError = exports.ValidationError = exports.UniqueConstraintError = exports.TurbineErrorCode = exports.TurbineError = exports.TimeoutError = exports.setErrorMessageMode = exports.SerializationFailureError = exports.RelationError = exports.NotNullViolationError = exports.NotFoundError = exports.MigrationError = exports.getErrorMessageMode = exports.ForeignKeyError = exports.DeadlockError = exports.ConnectionError = exports.CircularRelationError = exports.CheckConstraintError = exports.TurbineClient = exports.TransactionClient = void 0;
37
+ exports.turbineHttp = exports.schemaToSQLString = exports.schemaToSQL = exports.schemaPush = exports.schemaDiff = exports.table = exports.defineSchema = exports.column = exports.ColumnBuilder = exports.snakeToPascal = exports.snakeToCamel = exports.singularize = exports.pgTypeToTs = exports.pgArrayType = exports.isDateType = exports.camelToSnake = exports.QueryInterface = exports.pipelineSupported = exports.executePipeline = exports.introspect = exports.generate = exports.wrapPgError = exports.ValidationError = exports.UniqueConstraintError = exports.TurbineErrorCode = exports.TurbineError = exports.TimeoutError = exports.setErrorMessageMode = exports.SerializationFailureError = exports.RelationError = exports.PipelineError = exports.NotNullViolationError = exports.NotFoundError = exports.MigrationError = exports.getErrorMessageMode = exports.ForeignKeyError = exports.DeadlockError = exports.ConnectionError = exports.CircularRelationError = exports.CheckConstraintError = exports.TurbineClient = exports.TransactionClient = void 0;
38
38
  // Client
39
39
  var client_js_1 = require("./client.js");
40
40
  Object.defineProperty(exports, "TransactionClient", { enumerable: true, get: function () { return client_js_1.TransactionClient; } });
@@ -50,6 +50,7 @@ Object.defineProperty(exports, "getErrorMessageMode", { enumerable: true, get: f
50
50
  Object.defineProperty(exports, "MigrationError", { enumerable: true, get: function () { return errors_js_1.MigrationError; } });
51
51
  Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_js_1.NotFoundError; } });
52
52
  Object.defineProperty(exports, "NotNullViolationError", { enumerable: true, get: function () { return errors_js_1.NotNullViolationError; } });
53
+ Object.defineProperty(exports, "PipelineError", { enumerable: true, get: function () { return errors_js_1.PipelineError; } });
53
54
  Object.defineProperty(exports, "RelationError", { enumerable: true, get: function () { return errors_js_1.RelationError; } });
54
55
  Object.defineProperty(exports, "SerializationFailureError", { enumerable: true, get: function () { return errors_js_1.SerializationFailureError; } });
55
56
  Object.defineProperty(exports, "setErrorMessageMode", { enumerable: true, get: function () { return errors_js_1.setErrorMessageMode; } });
@@ -68,6 +69,7 @@ Object.defineProperty(exports, "introspect", { enumerable: true, get: function (
68
69
  // Pipeline
69
70
  var pipeline_js_1 = require("./pipeline.js");
70
71
  Object.defineProperty(exports, "executePipeline", { enumerable: true, get: function () { return pipeline_js_1.executePipeline; } });
72
+ Object.defineProperty(exports, "pipelineSupported", { enumerable: true, get: function () { return pipeline_js_1.pipelineSupported; } });
71
73
  // Query builder
72
74
  var query_js_1 = require("./query.js");
73
75
  Object.defineProperty(exports, "QueryInterface", { enumerable: true, get: function () { return query_js_1.QueryInterface; } });