turbine-orm 0.19.2 → 0.22.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.
Files changed (53) hide show
  1. package/README.md +99 -18
  2. package/dist/adapters/cockroachdb.js +4 -9
  3. package/dist/cjs/adapters/cockroachdb.js +4 -9
  4. package/dist/cjs/cli/index.js +6 -3
  5. package/dist/cjs/cli/observe-ui.js +12 -2
  6. package/dist/cjs/cli/observe.js +6 -7
  7. package/dist/cjs/cli/studio.js +6 -7
  8. package/dist/cjs/client.js +44 -22
  9. package/dist/cjs/dialect.js +116 -0
  10. package/dist/cjs/errors.js +19 -1
  11. package/dist/cjs/generate.js +4 -0
  12. package/dist/cjs/index.js +3 -2
  13. package/dist/cjs/introspect.js +20 -0
  14. package/dist/cjs/mssql.js +1338 -0
  15. package/dist/cjs/mysql.js +1052 -0
  16. package/dist/cjs/powdb.js +851 -0
  17. package/dist/cjs/powql.js +903 -0
  18. package/dist/cjs/query/builder.js +293 -73
  19. package/dist/cjs/sqlite.js +849 -0
  20. package/dist/cjs/typed-sql.js +9 -7
  21. package/dist/cli/index.js +6 -3
  22. package/dist/cli/observe-ui.d.ts +1 -1
  23. package/dist/cli/observe-ui.js +12 -2
  24. package/dist/cli/observe.js +7 -8
  25. package/dist/cli/studio.js +7 -8
  26. package/dist/cli/ui.d.ts +1 -1
  27. package/dist/client.d.ts +23 -1
  28. package/dist/client.js +45 -23
  29. package/dist/dialect.d.ts +258 -1
  30. package/dist/dialect.js +83 -0
  31. package/dist/errors.d.ts +12 -0
  32. package/dist/errors.js +17 -0
  33. package/dist/generate.js +4 -0
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.js +1 -1
  36. package/dist/introspect.d.ts +18 -0
  37. package/dist/introspect.js +19 -0
  38. package/dist/mssql.d.ts +233 -0
  39. package/dist/mssql.js +1298 -0
  40. package/dist/mysql.d.ts +174 -0
  41. package/dist/mysql.js +1012 -0
  42. package/dist/powdb.d.ts +338 -0
  43. package/dist/powdb.js +802 -0
  44. package/dist/powql.d.ts +153 -0
  45. package/dist/powql.js +900 -0
  46. package/dist/query/builder.d.ts +105 -0
  47. package/dist/query/builder.js +294 -74
  48. package/dist/query/index.d.ts +1 -1
  49. package/dist/sqlite.d.ts +144 -0
  50. package/dist/sqlite.js +842 -0
  51. package/dist/typed-sql.d.ts +7 -5
  52. package/dist/typed-sql.js +9 -7
  53. package/package.json +45 -1
@@ -14,6 +14,12 @@ import type pg from 'pg';
14
14
  import type { Dialect } from '../dialect.js';
15
15
  import type { SchemaMetadata } from '../schema.js';
16
16
  import type { AggregateArgs, AggregateResult, CountArgs, CreateArgs, CreateManyArgs, DeleteArgs, DeleteManyArgs, FindManyArgs, FindManyStreamArgs, FindUniqueArgs, GroupByArgs, QueryResult, TypedWithClause, UpdateArgs, UpdateManyArgs, UpsertArgs, WithClause } from './types.js';
17
+ /**
18
+ * Runs a SQL statement and resolves its raw result. Passed to a
19
+ * {@link DeferredQuery.reselect} plan so it can run the write and the follow-up
20
+ * SELECT through the same timeout/instrumentation path as the primary query.
21
+ */
22
+ export type ReselectExecutor = (sql: string, params: unknown[], preparedName?: string) => Promise<pg.QueryResult>;
17
23
  export interface DeferredQuery<T> {
18
24
  /** SQL text with $1, $2 placeholders */
19
25
  sql: string;
@@ -25,6 +31,15 @@ export interface DeferredQuery<T> {
25
31
  tag: string;
26
32
  /** Prepared statement name (t_<16hex>). Set when SQL cache is enabled. */
27
33
  preparedName?: string;
34
+ /**
35
+ * Execution plan for dialects whose {@link Dialect.resultStrategy} is
36
+ * `'reselect'` (no RETURNING — e.g. MySQL). Owns the statement ordering: it
37
+ * runs the write and the follow-up row-fetching SELECT(s) via `exec`, and
38
+ * resolves the result whose rows {@link DeferredQuery.transform} consumes.
39
+ * Absent for `'returning'`/`'output'` dialects (the statement returns its own
40
+ * rows), so the PostgreSQL path never allocates or consults it.
41
+ */
42
+ reselect?: (exec: ReselectExecutor) => Promise<pg.QueryResult>;
28
43
  }
29
44
  /** Middleware function type — imported from client to avoid circular deps */
30
45
  export type MiddlewareFn = (params: {
@@ -83,6 +98,14 @@ export interface QueryInterfaceOptions {
83
98
  _txScoped?: boolean;
84
99
  /** @internal Callback from TurbineClient for query event emission. */
85
100
  _onQuery?: (event: QueryEvent) => void;
101
+ /**
102
+ * @internal Factory that builds the per-table query interface. Defaults to
103
+ * `new QueryInterface` (the SQL path). Non-SQL backends (PowDB) supply a
104
+ * factory returning a structurally-compatible interface that generates their
105
+ * own query language instead of SQL. The SQL dialects never set this, so their
106
+ * `table()` behavior is byte-identical.
107
+ */
108
+ queryInterfaceFactory?: (pool: pg.Pool, table: string, schema: SchemaMetadata, middlewares: MiddlewareFn[], options: QueryInterfaceOptions) => QueryInterface<object>;
86
109
  }
87
110
  export declare class QueryInterface<T extends object, R extends object = {}> {
88
111
  private readonly pool;
@@ -133,6 +156,54 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
133
156
  private q;
134
157
  /** Return the active dialect's placeholder for a 1-indexed parameter position. */
135
158
  private p;
159
+ /**
160
+ * Cast an aggregate expression to an integer/float result type through the
161
+ * active dialect. PostgreSQL keeps the historical postfix cast (`expr::int` /
162
+ * `expr::float`); SQLite (no `::` operator) maps to `CAST(expr AS INTEGER/REAL)`.
163
+ * Falls back to the Postgres postfix cast for dialects without the hook.
164
+ */
165
+ private castAgg;
166
+ /**
167
+ * Build the trailing pagination clause for an OUTER SELECT. PostgreSQL/MySQL/
168
+ * SQLite use ` LIMIT <ph>` and/or ` OFFSET <ph>`. SQL Server has no `LIMIT`, so
169
+ * its dialect implements {@link Dialect.buildLimitOffset} to emit
170
+ * `[ORDER BY (SELECT NULL)] OFFSET <off> ROWS [FETCH NEXT <lim> ROWS ONLY]`.
171
+ * Param-push order (limit before offset) is owned by the caller and unchanged —
172
+ * this only varies the SQL text, so PG output stays byte-identical.
173
+ */
174
+ private buildPagination;
175
+ /**
176
+ * The single-row limit appended to findUnique / findFirst-style lookups. ` LIMIT 1`
177
+ * for PG/MySQL/SQLite; SQL Server routes through {@link Dialect.buildLimitOffset}
178
+ * (literal `1`, no params) → ` ORDER BY (SELECT NULL) OFFSET 0 ROWS FETCH NEXT 1
179
+ * ROWS ONLY`. No params are pushed, so the collect path is unaffected.
180
+ */
181
+ private limitOneClause;
182
+ /**
183
+ * Validate a LIMIT/OFFSET value as a non-negative integer and return it as an
184
+ * inline SQL literal. Used only on `dialect.inlineLimitOffset` engines (MySQL).
185
+ * The input is always a Turbine-controlled pagination value, never a raw user
186
+ * string — and this guard guarantees the output is `String` of a validated
187
+ * integer, so inlining cannot inject SQL.
188
+ */
189
+ private limitOffsetLiteral;
190
+ /**
191
+ * Resolve a LIMIT/OFFSET value to either an inline literal (no param pushed, on
192
+ * `dialect.inlineLimitOffset` engines) or a bound placeholder (the value is
193
+ * pushed to `params`). Build and collect paths both gate on the same flag so
194
+ * the param order stays mirrored; PG/SQLite/SQL Server keep parameterizing and
195
+ * stay byte-identical.
196
+ */
197
+ private paginationRef;
198
+ /**
199
+ * Build an `IN` / `NOT IN` predicate through the active dialect. PostgreSQL
200
+ * keeps the array-param form (`expr = ANY($n)` / `expr != ALL($n)`); other
201
+ * engines (SQLite) use a length-independent single-placeholder form. Paired
202
+ * with {@link inParam}, which supplies the single bound value.
203
+ */
204
+ private inClause;
205
+ /** The single bound parameter for an `IN` list (PG: the array; SQLite: a JSON string). */
206
+ private inParam;
136
207
  /**
137
208
  * Return cache hit/miss statistics for this QueryInterface instance.
138
209
  * Useful for monitoring and benchmarking.
@@ -164,6 +235,33 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
164
235
  * pg driver errors are translated to typed Turbine errors via wrapPgError.
165
236
  */
166
237
  private queryWithTimeout;
238
+ /**
239
+ * Execute a write `DeferredQuery` (create/update/delete/upsert) according to
240
+ * the active dialect's {@link Dialect.resultStrategy}, then apply its
241
+ * transform.
242
+ *
243
+ * - `'returning'` / `'output'`: the statement returns its own affected rows
244
+ * (`RETURNING *` / `OUTPUT INSERTED.*`). Byte-identical to the historical
245
+ * single `queryWithTimeout` + `transform(result)` path — the PostgreSQL
246
+ * route is unchanged.
247
+ * - `'reselect'`: the engine cannot return rows from a write, so the build
248
+ * method attached a {@link DeferredQuery.reselect} plan that runs the
249
+ * write and a follow-up SELECT; the SELECT's rows feed the transform.
250
+ */
251
+ private executeMutation;
252
+ /**
253
+ * Build a `SELECT * ... WHERE <predicate>` that re-fetches the row(s) matched
254
+ * by a write's `where` clause. Used by the `'reselect'` result strategy to
255
+ * return rows from non-RETURNING engines. Reuses the same parameterized WHERE
256
+ * builder as reads, so no user value is interpolated.
257
+ */
258
+ private buildReselectByWhere;
259
+ /**
260
+ * Best-effort extraction of an auto-generated primary key from a write
261
+ * result for `'reselect'` engines (e.g. mysql2's `insertId`). Returns
262
+ * `undefined` when the driver exposes no such field.
263
+ */
264
+ private mutationInsertId;
167
265
  /**
168
266
  * Execute a query through the middleware chain.
169
267
  * If no middlewares are registered, executes directly.
@@ -232,6 +330,13 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
232
330
  buildFindUniqueOrThrow<W extends TypedWithClause<R> = {}>(args: FindUniqueArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T>;
233
331
  create(args: CreateArgs<T, R>): Promise<T>;
234
332
  buildCreate(args: CreateArgs<T>): DeferredQuery<T>;
333
+ /**
334
+ * Build the `'reselect'` plan for {@link buildCreate}: run the INSERT, then
335
+ * `SELECT * WHERE pk = ?`. Returns `undefined` (skipped) unless the active
336
+ * dialect's result strategy is `'reselect'`, so the PostgreSQL/RETURNING path
337
+ * pays nothing. Not yet wired to a real non-RETURNING engine.
338
+ */
339
+ private makeCreateReselect;
235
340
  createMany(args: CreateManyArgs<T>): Promise<T[]>;
236
341
  buildCreateMany(args: CreateManyArgs<T>): DeferredQuery<T[]>;
237
342
  update(args: UpdateArgs<T, R>): Promise<T>;