turbine-orm 0.34.0 → 0.35.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/dist/cjs/client.js +26 -4
- package/dist/cjs/dialect.js +1 -0
- package/dist/cjs/errors.js +41 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/mssql.js +5 -0
- package/dist/cjs/mysql.js +4 -0
- package/dist/cjs/powdb.js +156 -24
- package/dist/cjs/powql.js +448 -39
- package/dist/cjs/query/builder.js +60 -0
- package/dist/cjs/sqlite.js +3 -0
- package/dist/client.d.ts +32 -5
- package/dist/client.js +26 -4
- package/dist/dialect.d.ts +13 -0
- package/dist/dialect.js +1 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +39 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/mssql.js +5 -0
- package/dist/mysql.js +4 -0
- package/dist/powdb.d.ts +115 -9
- package/dist/powdb.js +157 -25
- package/dist/powql.d.ts +133 -3
- package/dist/powql.js +449 -40
- package/dist/query/builder.d.ts +36 -1
- package/dist/query/builder.js +60 -0
- package/dist/query/deferred.d.ts +6 -2
- package/dist/query/types.d.ts +10 -6
- package/dist/sqlite.js +3 -0
- package/package.json +3 -3
package/dist/query/builder.d.ts
CHANGED
|
@@ -36,7 +36,12 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
36
36
|
private readonly warnOnUnlimited;
|
|
37
37
|
private readonly utcTimestamps;
|
|
38
38
|
private readonly preparedStatementsEnabled;
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Whether the SQL template cache is active. Set once in the constructor.
|
|
41
|
+
* Mutable (not `readonly`) only so {@link withSqlCacheDisabled} can flip it
|
|
42
|
+
* off around a single synchronous compile (see {@link explain}).
|
|
43
|
+
*/
|
|
44
|
+
private sqlCacheEnabled;
|
|
40
45
|
private readonly dialect;
|
|
41
46
|
/** Client-level default relation-loading strategy ('join' unless configured). */
|
|
42
47
|
private readonly relationLoadStrategy;
|
|
@@ -290,6 +295,36 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
290
295
|
private runFindUniqueBatched;
|
|
291
296
|
buildFindUnique<W extends TypedWithClause<R> = {}>(args: FindUniqueArgs<T, R, W, Record<string, boolean> | undefined, Record<string, boolean> | undefined>): DeferredQuery<T | null>;
|
|
292
297
|
findMany<W extends TypedWithClause<R> = {}, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined>(args?: FindManyArgs<T, R, W, S, O>): Promise<QueryResult<T, R, W, S, O>[]>;
|
|
298
|
+
/**
|
|
299
|
+
* Return the engine's query plan for a {@link findMany}-shaped query as plain
|
|
300
|
+
* text lines: a diagnostic surface for inspecting how the database will run a
|
|
301
|
+
* query (index usage, join strategy, scan type).
|
|
302
|
+
*
|
|
303
|
+
* The compiled SELECT is prefixed with the dialect's explain syntax
|
|
304
|
+
* (Postgres `EXPLAIN`, SQLite `EXPLAIN QUERY PLAN`, MySQL `EXPLAIN
|
|
305
|
+
* FORMAT=TREE`) and run as a read. The findMany args are compiled with the
|
|
306
|
+
* SQL template cache disabled, so an explain never reads or writes the shared
|
|
307
|
+
* cache. Middleware is NOT applied: the returned rows are plan text, not
|
|
308
|
+
* entity rows. Each result row is flattened to one line by joining its column
|
|
309
|
+
* values with a single space (Postgres returns one `QUERY PLAN` text column,
|
|
310
|
+
* SQLite's `EXPLAIN QUERY PLAN` returns four, MySQL's tree format one).
|
|
311
|
+
*
|
|
312
|
+
* Only `findMany` shapes are supported (where / orderBy / with / limit /
|
|
313
|
+
* pagination). Engines whose plan cannot be requested in-band from a compiled
|
|
314
|
+
* query (SQL Server, whose SHOWPLAN is a session toggle) throw
|
|
315
|
+
* {@link UnsupportedFeatureError} (E017).
|
|
316
|
+
*
|
|
317
|
+
* The plan text itself is engine-owned and NOT covered by semver: its content
|
|
318
|
+
* and formatting can change with the underlying database version.
|
|
319
|
+
*/
|
|
320
|
+
explain(args?: FindManyArgs<T, R>): Promise<string[]>;
|
|
321
|
+
/**
|
|
322
|
+
* Run `fn` with the SQL template cache forced off, restoring the prior state
|
|
323
|
+
* afterward. Used by {@link explain}, whose one-off prefixed statement must
|
|
324
|
+
* neither read nor write the shared cache. `fn` is synchronous, so no query
|
|
325
|
+
* interleaves between the toggle and its restore.
|
|
326
|
+
*/
|
|
327
|
+
private withSqlCacheDisabled;
|
|
293
328
|
/**
|
|
294
329
|
* Emit a one-time `console.warn` when {@link findMany} is called without an
|
|
295
330
|
* explicit `limit`/`take` and `warnOnUnlimited` has not been disabled.
|
package/dist/query/builder.js
CHANGED
|
@@ -141,6 +141,11 @@ export class QueryInterface {
|
|
|
141
141
|
warnOnUnlimited;
|
|
142
142
|
utcTimestamps;
|
|
143
143
|
preparedStatementsEnabled;
|
|
144
|
+
/**
|
|
145
|
+
* Whether the SQL template cache is active. Set once in the constructor.
|
|
146
|
+
* Mutable (not `readonly`) only so {@link withSqlCacheDisabled} can flip it
|
|
147
|
+
* off around a single synchronous compile (see {@link explain}).
|
|
148
|
+
*/
|
|
144
149
|
sqlCacheEnabled;
|
|
145
150
|
dialect;
|
|
146
151
|
/** Client-level default relation-loading strategy ('join' unless configured). */
|
|
@@ -834,6 +839,61 @@ export class QueryInterface {
|
|
|
834
839
|
return deferred.transform(result);
|
|
835
840
|
});
|
|
836
841
|
}
|
|
842
|
+
/**
|
|
843
|
+
* Return the engine's query plan for a {@link findMany}-shaped query as plain
|
|
844
|
+
* text lines: a diagnostic surface for inspecting how the database will run a
|
|
845
|
+
* query (index usage, join strategy, scan type).
|
|
846
|
+
*
|
|
847
|
+
* The compiled SELECT is prefixed with the dialect's explain syntax
|
|
848
|
+
* (Postgres `EXPLAIN`, SQLite `EXPLAIN QUERY PLAN`, MySQL `EXPLAIN
|
|
849
|
+
* FORMAT=TREE`) and run as a read. The findMany args are compiled with the
|
|
850
|
+
* SQL template cache disabled, so an explain never reads or writes the shared
|
|
851
|
+
* cache. Middleware is NOT applied: the returned rows are plan text, not
|
|
852
|
+
* entity rows. Each result row is flattened to one line by joining its column
|
|
853
|
+
* values with a single space (Postgres returns one `QUERY PLAN` text column,
|
|
854
|
+
* SQLite's `EXPLAIN QUERY PLAN` returns four, MySQL's tree format one).
|
|
855
|
+
*
|
|
856
|
+
* Only `findMany` shapes are supported (where / orderBy / with / limit /
|
|
857
|
+
* pagination). Engines whose plan cannot be requested in-band from a compiled
|
|
858
|
+
* query (SQL Server, whose SHOWPLAN is a session toggle) throw
|
|
859
|
+
* {@link UnsupportedFeatureError} (E017).
|
|
860
|
+
*
|
|
861
|
+
* The plan text itself is engine-owned and NOT covered by semver: its content
|
|
862
|
+
* and formatting can change with the underlying database version.
|
|
863
|
+
*/
|
|
864
|
+
async explain(args) {
|
|
865
|
+
const explainSyntax = this.dialect.explainQuery;
|
|
866
|
+
if (!explainSyntax) {
|
|
867
|
+
throw new UnsupportedFeatureError('explain()', this.dialect.name, 'This engine cannot explain a compiled query in-band.');
|
|
868
|
+
}
|
|
869
|
+
// Compile the findMany SQL with the cache disabled: the prefixed EXPLAIN
|
|
870
|
+
// statement is a one-off diagnostic and must never read or write the shared
|
|
871
|
+
// query-template cache.
|
|
872
|
+
const deferred = this.withSqlCacheDisabled(() => this.buildFindMany(args));
|
|
873
|
+
const sql = `${explainSyntax.prefix} ${deferred.sql}`;
|
|
874
|
+
this.currentAction = 'explain';
|
|
875
|
+
// No preparedName: keep the diagnostic statement out of the prepared path.
|
|
876
|
+
const result = await this.queryWithTimeout(sql, deferred.params, args?.timeout);
|
|
877
|
+
return result.rows.map((row) => Object.values(row)
|
|
878
|
+
.map((value) => (typeof value === 'string' ? value : String(value)))
|
|
879
|
+
.join(' '));
|
|
880
|
+
}
|
|
881
|
+
/**
|
|
882
|
+
* Run `fn` with the SQL template cache forced off, restoring the prior state
|
|
883
|
+
* afterward. Used by {@link explain}, whose one-off prefixed statement must
|
|
884
|
+
* neither read nor write the shared cache. `fn` is synchronous, so no query
|
|
885
|
+
* interleaves between the toggle and its restore.
|
|
886
|
+
*/
|
|
887
|
+
withSqlCacheDisabled(fn) {
|
|
888
|
+
const prev = this.sqlCacheEnabled;
|
|
889
|
+
this.sqlCacheEnabled = false;
|
|
890
|
+
try {
|
|
891
|
+
return fn();
|
|
892
|
+
}
|
|
893
|
+
finally {
|
|
894
|
+
this.sqlCacheEnabled = prev;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
837
897
|
/**
|
|
838
898
|
* Emit a one-time `console.warn` when {@link findMany} is called without an
|
|
839
899
|
* explicit `limit`/`take` and `warnOnUnlimited` has not been disabled.
|
package/dist/query/deferred.d.ts
CHANGED
|
@@ -111,8 +111,12 @@ export interface QueryInterfaceOptions {
|
|
|
111
111
|
*/
|
|
112
112
|
utcTimestamps?: boolean;
|
|
113
113
|
/**
|
|
114
|
-
* Client-level default relation-loading strategy for `with` clauses
|
|
115
|
-
* `relationLoadStrategy`
|
|
114
|
+
* Client-level default relation-loading strategy for `with` clauses; a
|
|
115
|
+
* per-query `relationLoadStrategy` arg overrides it. On SQL engines the default
|
|
116
|
+
* is `'join'` (one single-statement `json_agg` query). On PowDB the default is
|
|
117
|
+
* the batched loaders, and `'join'` opts INTO native server-side joins where
|
|
118
|
+
* eligible (ineligible relations fall back to the loaders per-relation and
|
|
119
|
+
* silently; see the PowDB docs).
|
|
116
120
|
*/
|
|
117
121
|
relationLoadStrategy?: RelationLoadStrategy;
|
|
118
122
|
/**
|
package/dist/query/types.d.ts
CHANGED
|
@@ -7,15 +7,19 @@ export type OrderDirection = 'asc' | 'desc';
|
|
|
7
7
|
/**
|
|
8
8
|
* How a query resolves its `with` relations.
|
|
9
9
|
*
|
|
10
|
-
* - `'join'
|
|
11
|
-
* `json_agg(json_build_object(...))` subqueries. One round-trip
|
|
12
|
-
* seek per parent row when the child FK is indexed.
|
|
13
|
-
*
|
|
10
|
+
* - `'join'`: one SQL statement with correlated
|
|
11
|
+
* `json_agg(json_build_object(...))` subqueries. One round-trip, an index
|
|
12
|
+
* seek per parent row when the child FK is indexed. On PowDB, `'join'`
|
|
13
|
+
* instead opts into native PowQL server-side joins where eligible.
|
|
14
|
+
* - `'batched'`: run the base query, then ONE flat follow-up query per
|
|
14
15
|
* relation (`WHERE fk = ANY($1)`), stitching children client-side. D levels
|
|
15
16
|
* cost D extra round-trips, but each is a single key-set lookup and rows come
|
|
16
|
-
* back flat
|
|
17
|
+
* back flat (a win when FK columns are unindexed or result sets are huge).
|
|
17
18
|
*
|
|
18
|
-
* Precedence: per-query arg > client `relationLoadStrategy` config >
|
|
19
|
+
* Precedence: per-query arg > client `relationLoadStrategy` config > the engine
|
|
20
|
+
* default. On SQL engines the default is `'join'`; on PowDB the default is the
|
|
21
|
+
* batched loaders (an ineligible relation falls back to them per-relation and
|
|
22
|
+
* silently even when `'join'` is requested).
|
|
19
23
|
*/
|
|
20
24
|
export type RelationLoadStrategy = 'join' | 'batched';
|
|
21
25
|
/**
|
package/dist/sqlite.js
CHANGED
|
@@ -372,6 +372,9 @@ export const sqliteDialect = {
|
|
|
372
372
|
supportsAdvisoryLock: false,
|
|
373
373
|
// No FROM-clause LATERAL: the opt-in lateral pick plan is Postgres-only.
|
|
374
374
|
supportsLateralJoin: false,
|
|
375
|
+
// SQLite explains a compiled query with `EXPLAIN QUERY PLAN` (four columns:
|
|
376
|
+
// id, parent, notused, detail), overriding the inherited Postgres `EXPLAIN`.
|
|
377
|
+
explainQuery: { prefix: 'EXPLAIN QUERY PLAN' },
|
|
375
378
|
// json_group_array / json_object have no inline ORDER BY argument, so every
|
|
376
379
|
// ordered to-many relation is forced through the inner-subquery rewrite.
|
|
377
380
|
aggSupportsInlineOrderBy: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "turbine-orm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.0",
|
|
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": {
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"@size-limit/esbuild": "^12.1.0",
|
|
104
104
|
"@size-limit/file": "^12.1.0",
|
|
105
105
|
"@types/node": "^26.1.0",
|
|
106
|
-
"@zvndev/powdb-client": "^0.
|
|
107
|
-
"@zvndev/powdb-embedded": "^0.
|
|
106
|
+
"@zvndev/powdb-client": "^0.15.0",
|
|
107
|
+
"@zvndev/powdb-embedded": "^0.15.0",
|
|
108
108
|
"c8": "^11.0.0",
|
|
109
109
|
"husky": "^9.1.7",
|
|
110
110
|
"lint-staged": "^17.0.8",
|