turbine-orm 0.30.0 → 0.32.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 +14 -3
- package/dist/cjs/mssql.js +24 -3
- package/dist/cjs/powdb.js +197 -50
- package/dist/cjs/powql.js +45 -2
- package/dist/cjs/query/batched-loader.js +34 -0
- package/dist/cjs/query/builder.js +758 -139
- package/dist/cjs/query/filters.js +77 -2
- package/dist/client.d.ts +13 -0
- package/dist/client.js +14 -3
- package/dist/index.d.ts +1 -1
- package/dist/mssql.js +24 -3
- package/dist/powdb.d.ts +33 -0
- package/dist/powdb.js +197 -50
- package/dist/powql.js +45 -2
- package/dist/query/batched-loader.d.ts +12 -0
- package/dist/query/batched-loader.js +33 -0
- package/dist/query/builder.d.ts +171 -5
- package/dist/query/builder.js +760 -141
- package/dist/query/filters.d.ts +40 -1
- package/dist/query/filters.js +73 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/types.d.ts +213 -22
- package/package.json +1 -1
package/dist/query/builder.d.ts
CHANGED
|
@@ -339,6 +339,27 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
339
339
|
buildCount(args?: CountArgs<T>): DeferredQuery<number>;
|
|
340
340
|
groupBy(args: GroupByArgs<T>): Promise<Record<string, unknown>[]>;
|
|
341
341
|
buildGroupBy(args: GroupByArgs<T>): DeferredQuery<Record<string, unknown>[]>;
|
|
342
|
+
/**
|
|
343
|
+
* Validate a JSON-path target (group key or aggregate target) in groupBy:
|
|
344
|
+
* the field must resolve to a real json/jsonb column and the path must be a
|
|
345
|
+
* non-empty array of keys/indexes. Returns the resolved snake_case column.
|
|
346
|
+
*/
|
|
347
|
+
private resolveJsonPathTarget;
|
|
348
|
+
/**
|
|
349
|
+
* Build the `distinctOn` row source for groupBy (PostgreSQL only: other
|
|
350
|
+
* engines throw {@link UnsupportedFeatureError} E017):
|
|
351
|
+
*
|
|
352
|
+
* ```sql
|
|
353
|
+
* (SELECT DISTINCT ON ("c1") * FROM "table"<WHERE> ORDER BY "c1", <orderBy>) AS "table"
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* The wrapper is aliased as the table name so every outer expression (group
|
|
357
|
+
* keys, aggregates, HAVING, ORDER BY) is byte-identical to the plain path.
|
|
358
|
+
* `distinctOn.orderBy` is required (it decides which row survives) and
|
|
359
|
+
* supports plain columns, {@link OrderBySpec} nulls, and JSON-path specs;
|
|
360
|
+
* JSON paths push their text[] param here, after the WHERE params.
|
|
361
|
+
*/
|
|
362
|
+
private buildDistinctOnSource;
|
|
342
363
|
/**
|
|
343
364
|
* Build the SQL fragments for a {@link HavingClause}.
|
|
344
365
|
*
|
|
@@ -349,6 +370,12 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
349
370
|
* comparison value is pushed onto the shared `params` array and referenced by
|
|
350
371
|
* a `$N` placeholder via {@link buildHavingNumericClauses} — there is no string
|
|
351
372
|
* interpolation of user values.
|
|
373
|
+
*
|
|
374
|
+
* `jsonAggExprs` (from {@link buildGroupBy}) maps `alias:aggKey` to the
|
|
375
|
+
* exact aggregate expression a JSON-path aggregate emitted in SELECT
|
|
376
|
+
* (including its already-bound path placeholder), so HAVING on a JSON-path
|
|
377
|
+
* aggregate alias reuses the same expression instead of resolving the alias
|
|
378
|
+
* as a column.
|
|
352
379
|
*/
|
|
353
380
|
private buildHavingClauses;
|
|
354
381
|
/**
|
|
@@ -436,7 +463,12 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
436
463
|
*/
|
|
437
464
|
private collectRelationFilterParams;
|
|
438
465
|
private collectRelFilterParams;
|
|
439
|
-
/**
|
|
466
|
+
/**
|
|
467
|
+
* Collect params from operator clauses. Mirrors buildOperatorClauses:
|
|
468
|
+
* {@link ColumnRef} values compile into the SQL text, so they push NOTHING -
|
|
469
|
+
* but they re-run the same validation (unknown ref / insensitive mode) so a
|
|
470
|
+
* warmed cache can never skip a check the build path enforces.
|
|
471
|
+
*/
|
|
440
472
|
private collectOperatorParams;
|
|
441
473
|
/**
|
|
442
474
|
* Collect params from JSON filter. Mirrors buildJsonFilterClauses exactly:
|
|
@@ -448,10 +480,10 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
448
480
|
/** Collect params from array filter. Mirrors buildArrayFilterClauses. */
|
|
449
481
|
private collectArrayFilterParams;
|
|
450
482
|
/**
|
|
451
|
-
* Collect params for an orderBy clause.
|
|
452
|
-
*
|
|
453
|
-
* parameterless. Mirrors buildOrderBy's push
|
|
454
|
-
* param re-collection stays in lockstep.
|
|
483
|
+
* Collect params for an orderBy clause. Vector KNN ordering pushes the
|
|
484
|
+
* `$n::vector` query vector and JSON-path ordering pushes its text[] path;
|
|
485
|
+
* plain direction ordering is parameterless. Mirrors buildOrderBy's push
|
|
486
|
+
* order exactly so the cached-SQL param re-collection stays in lockstep.
|
|
455
487
|
*/
|
|
456
488
|
private collectOrderByParams;
|
|
457
489
|
/**
|
|
@@ -611,9 +643,28 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
611
643
|
* differently-shaped wheres would share one cached SQL string.
|
|
612
644
|
*/
|
|
613
645
|
private fingerprintAliasWhere;
|
|
646
|
+
/**
|
|
647
|
+
* Validate a `{ col }` column reference against its table and return the
|
|
648
|
+
* resolved snake_case column name. Shared by the SQL-build path
|
|
649
|
+
* ({@link buildOperatorClauses}) and the cache-hit param-collect path
|
|
650
|
+
* (`collectOperatorParams`) so both always throw identically: a warmed
|
|
651
|
+
* cache can never skip the check.
|
|
652
|
+
*/
|
|
653
|
+
private resolveColumnRef;
|
|
654
|
+
/**
|
|
655
|
+
* Compile a `{ col }` reference to its quoted, prefix-matched SQL identifier.
|
|
656
|
+
* NO param is bound: the referenced column is part of the SQL text (and of
|
|
657
|
+
* the where fingerprint, see {@link fingerprintOperatorShape}).
|
|
658
|
+
*/
|
|
659
|
+
private columnRefSql;
|
|
614
660
|
/**
|
|
615
661
|
* Build SQL clauses for a single operator object on a column.
|
|
616
662
|
* Each operator key becomes its own clause, all ANDed together.
|
|
663
|
+
*
|
|
664
|
+
* `equals`/`not`/`gt`/`gte`/`lt`/`lte` also accept a {@link ColumnRef}
|
|
665
|
+
* (`{ col: 'otherField' }`) which compiles to a column-to-column comparison
|
|
666
|
+
* against `refCtx`: no param bound, so `collectOperatorParams` mirrors by
|
|
667
|
+
* pushing nothing and the referenced name lives in the fingerprint.
|
|
617
668
|
*/
|
|
618
669
|
private buildOperatorClauses;
|
|
619
670
|
/**
|
|
@@ -647,6 +698,33 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
647
698
|
* {@link UnsupportedFeatureError} (E017) instead of broken SQL.
|
|
648
699
|
*/
|
|
649
700
|
private nullsSuffix;
|
|
701
|
+
/**
|
|
702
|
+
* Resolve an orderBy key to its snake_case column via the table's columnMap
|
|
703
|
+
* (camelToSnake fallback), throwing the SAME unknown-field E003 the top-level
|
|
704
|
+
* where path uses. Shared by top-level JSON-path ordering and every nested
|
|
705
|
+
* relation orderBy path so nested orderBy accepts exactly what top-level
|
|
706
|
+
* accepts (the 0.30.x bug: nested orderBy skipped the columnMap and rejected
|
|
707
|
+
* camelCase-named DB columns like "sortOrder").
|
|
708
|
+
*/
|
|
709
|
+
private resolveOrderByColumn;
|
|
710
|
+
/**
|
|
711
|
+
* Validate a {@link JsonPathOrderBy} entry: column must exist AND be
|
|
712
|
+
* json/jsonb, path must be a non-empty array of keys/indexes: and return
|
|
713
|
+
* the resolved column. Shared by the SQL-build path
|
|
714
|
+
* ({@link buildJsonPathOrderEntry}) and the cache-hit param-collect mirrors
|
|
715
|
+
* so both always throw identically.
|
|
716
|
+
*/
|
|
717
|
+
private validateJsonPathOrderBy;
|
|
718
|
+
/**
|
|
719
|
+
* Compile one {@link JsonPathOrderBy} entry:
|
|
720
|
+
* `("col" #>> $n::text[])::numeric ASC`: the numeric cast only with
|
|
721
|
+
* `type: 'numeric'` (default is text comparison), the extraction routed
|
|
722
|
+
* through the dialect's JSON hook exactly like the JSON where-filters, the
|
|
723
|
+
* path bound as ONE text[] param (mirrored by the order-param collectors).
|
|
724
|
+
* `prefix` scopes the column (`''` top-level, `t0.` inside a relation
|
|
725
|
+
* subquery).
|
|
726
|
+
*/
|
|
727
|
+
private buildJsonPathOrderEntry;
|
|
650
728
|
/**
|
|
651
729
|
* Compile a relation ordering term. For a to-many relation the only allowed
|
|
652
730
|
* key is `_count`, which becomes a correlated `COUNT(*)` subquery. For a
|
|
@@ -655,8 +733,77 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
655
733
|
*
|
|
656
734
|
* Validation: relation must exist (E005); to-many only allows `_count`, and
|
|
657
735
|
* to-one only allows real target columns (E003).
|
|
736
|
+
*
|
|
737
|
+
* `ctx` generalizes the term beyond the root table: inside a relation
|
|
738
|
+
* subquery's orderBy the relations live on the TARGET table's metadata and
|
|
739
|
+
* the correlation parent is the relation's alias, not `this.table`.
|
|
658
740
|
*/
|
|
659
741
|
private buildRelationOrderBy;
|
|
742
|
+
/**
|
|
743
|
+
* Validate a {@link RelationPickOrderBy} entry's scope and shape. Shared by
|
|
744
|
+
* the SQL-build path ({@link buildRelationPickOrderBy}) and the cache-hit
|
|
745
|
+
* param-collect mirror ({@link collectRelationPickOrderParams}) so both
|
|
746
|
+
* always throw identically:
|
|
747
|
+
*
|
|
748
|
+
* - `nested` (inside a relation subquery's orderBy or a pick.orderBy):
|
|
749
|
+
* top-level findMany only in this release (E003),
|
|
750
|
+
* - manyToMany: not supported (E003 naming the limitation),
|
|
751
|
+
* - to-one: order by the target column directly instead (E003),
|
|
752
|
+
* - `pick.orderBy` is REQUIRED (deterministic row choice),
|
|
753
|
+
* - `by` must be a target column name or a `{ field, path }` JSON-path spec.
|
|
754
|
+
*/
|
|
755
|
+
private pickOrderNestedError;
|
|
756
|
+
private validatePickOrderBy;
|
|
757
|
+
/**
|
|
758
|
+
* Compile a {@link RelationPickOrderBy} term: a correlated scalar subquery
|
|
759
|
+
* that picks ONE related row (`ORDER BY <pick.orderBy> LIMIT 1`, optionally
|
|
760
|
+
* filtered by `pick.where` and the target's global filter) and surfaces one
|
|
761
|
+
* value from it (a plain target column or a JSON-path extraction) as the
|
|
762
|
+
* parent ORDER BY key:
|
|
763
|
+
*
|
|
764
|
+
* ```sql
|
|
765
|
+
* (SELECT ord0."data" #>> $1::text[] FROM "versions" ord0
|
|
766
|
+
* WHERE ord0."instance_id" = "instances"."id" AND ord0."is_current" = $2
|
|
767
|
+
* ORDER BY ord0."created_at" DESC LIMIT 1) ASC NULLS LAST
|
|
768
|
+
* ```
|
|
769
|
+
*
|
|
770
|
+
* Param-push order (mirrored EXACTLY by
|
|
771
|
+
* {@link collectRelationPickOrderParams}): `by` JSON path (if any) →
|
|
772
|
+
* target global filter → `pick.where` → `pick.orderBy` JSON paths.
|
|
773
|
+
*/
|
|
774
|
+
private buildRelationPickOrderBy;
|
|
775
|
+
/**
|
|
776
|
+
* Param-collect mirror of {@link buildRelationPickOrderBy}: re-runs the same
|
|
777
|
+
* validation (a warmed cache can never skip it), then pushes in the same
|
|
778
|
+
* order: `by` JSON path → target global filter → `pick.where` →
|
|
779
|
+
* `pick.orderBy` JSON paths.
|
|
780
|
+
*/
|
|
781
|
+
private collectRelationPickOrderParams;
|
|
782
|
+
/**
|
|
783
|
+
* Compile the ORDER BY terms of a relation `with` clause against the
|
|
784
|
+
* relation's table alias. One unified path for every relation shape
|
|
785
|
+
* (hasMany / manyToMany / belongsTo / hasOne) supporting exactly what the
|
|
786
|
+
* top-level orderBy accepts at this level:
|
|
787
|
+
*
|
|
788
|
+
* - scalar columns via columnMap resolution (camelToSnake fallback) with
|
|
789
|
+
* {@link OrderBySpec} nulls placement,
|
|
790
|
+
* - {@link JsonPathOrderBy} entries (path bound as one text[] param),
|
|
791
|
+
* - relation ordering on the TARGET's relations (`_count` for to-many, a
|
|
792
|
+
* target column for to-one), correlated to the relation alias,
|
|
793
|
+
* - vector KNN ordering stays top-level-only (E003, same as before).
|
|
794
|
+
*
|
|
795
|
+
* Param pushes (JSON paths, relation-order global filters) MUST be mirrored,
|
|
796
|
+
* in the same order, by {@link collectRelationOrderParams}.
|
|
797
|
+
*/
|
|
798
|
+
private buildRelationOrderClause;
|
|
799
|
+
/**
|
|
800
|
+
* Param-collect mirror of {@link buildRelationOrderClause}: JSON-path
|
|
801
|
+
* entries push their path (one text[] param each); relation-order entries
|
|
802
|
+
* mirror {@link collectOrderByParams}' relation branch (count / to-one
|
|
803
|
+
* global-filter params); scalar entries push nothing but re-run the same
|
|
804
|
+
* column validation so a warmed cache can never skip it.
|
|
805
|
+
*/
|
|
806
|
+
private collectRelationOrderParams;
|
|
660
807
|
/**
|
|
661
808
|
* Build a correlated `(SELECT COUNT(*) …)` scalar subquery for a to-many
|
|
662
809
|
* relation, correlated to `parentRef`. hasMany counts child rows via the FK;
|
|
@@ -929,6 +1076,13 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
929
1076
|
* Used to detect JSONB/array columns for specialized operators.
|
|
930
1077
|
* Uses pre-computed Map for O(1) lookup instead of linear scan.
|
|
931
1078
|
*/
|
|
1079
|
+
/**
|
|
1080
|
+
* Case-insensitive json/jsonb column-type check. Postgres reports lowercase
|
|
1081
|
+
* udt_names, but SQLite/MySQL introspection surfaces the DECLARED type
|
|
1082
|
+
* (e.g. `JSON`), so every JSON-feature gate compares through this predicate
|
|
1083
|
+
* — build and collect sides alike, keeping the SQL-cache lockstep.
|
|
1084
|
+
*/
|
|
1085
|
+
private isJsonColumnType;
|
|
932
1086
|
private getColumnPgType;
|
|
933
1087
|
/**
|
|
934
1088
|
* Get the Postgres base element type for an array column.
|
|
@@ -953,6 +1107,18 @@ export declare class QueryInterface<T extends object, R extends object = {}> {
|
|
|
953
1107
|
* stays byte-identical to {@link collectJsonFilterParams}.
|
|
954
1108
|
*/
|
|
955
1109
|
private buildJsonFilterClauses;
|
|
1110
|
+
/**
|
|
1111
|
+
* Bind value for a JSON path parameter, encoded per dialect. PostgreSQL's
|
|
1112
|
+
* `#>>` takes a `text[]` (the segments as strings — or `nativeForm` when the
|
|
1113
|
+
* caller has a specific native binding, e.g. JsonFilter's raw path array).
|
|
1114
|
+
* Every other engine's JSON function (`json_extract` / `JSON_EXTRACT` /
|
|
1115
|
+
* `JSON_VALUE`) takes a `'$'`-rooted JSONPath STRING: binding the raw array
|
|
1116
|
+
* would arrive as `'["a"]'` (the driver shims JSON.stringify non-primitive
|
|
1117
|
+
* params) and fail at runtime with the engine's bad-JSON-path error. The
|
|
1118
|
+
* encoded path stays a bound parameter — never spliced into SQL text — so
|
|
1119
|
+
* the build/collect param mirrors stay in lockstep and injection-safe.
|
|
1120
|
+
*/
|
|
1121
|
+
private jsonPathParam;
|
|
956
1122
|
/**
|
|
957
1123
|
* Cast an extracted JSON path text value to a numeric type for range
|
|
958
1124
|
* comparison. PostgreSQL uses `(expr)::numeric` (exact — the right way to
|