@danceroutine/tango-orm 1.5.0 → 1.7.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/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/manager/ManagerLike.d.ts +19 -0
- package/dist/manager/ModelManager.d.ts +24 -1
- package/dist/manager/index.js +2 -2
- package/dist/manager-C6oJ2tAF.js +1 -1
- package/dist/query/QuerySet.d.ts +33 -3
- package/dist/query/domain/QueryResult.d.ts +34 -3
- package/dist/query/domain/index.d.ts +1 -1
- package/dist/query/index.d.ts +1 -0
- package/dist/query/index.js +2 -2
- package/dist/query/internal/isQNodeLike.d.ts +3 -0
- package/dist/{query-DYiJ5m_B.js → query-FZJoSCg4.js} +162 -30
- package/dist/query-FZJoSCg4.js.map +1 -0
- package/dist/{registerModelObjects-B1VzZ072.js → registerModelObjects-C-1RbUHS.js} +124 -2
- package/dist/registerModelObjects-C-1RbUHS.js.map +1 -0
- package/dist/runtime/index.js +2 -2
- package/dist/runtime-ByXbpVBS.js +1 -1
- package/package.json +6 -6
- package/dist/query-DYiJ5m_B.js.map +0 -1
- package/dist/registerModelObjects-B1VzZ072.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ export type { Adapter, AdapterConfig, DBClient } from './connection/index';
|
|
|
14
14
|
export { PostgresAdapter, SqliteAdapter } from './connection/index';
|
|
15
15
|
export { ModelManager } from './manager/index';
|
|
16
16
|
export type { ManagerLike } from './manager/index';
|
|
17
|
-
export { Q, QBuilder, QueryCompiler, QuerySet } from './query/index';
|
|
17
|
+
export { Q, QBuilder, QueryCompiler, QueryResult, QuerySet } from './query/index';
|
|
18
18
|
export type { QueryExecutor } from './query/index';
|
|
19
|
-
export type { CompiledQuery, Dialect, Direction, FilterInput, FilterKey, FilterValue, LookupType, OrderSpec, OrderToken, QNode,
|
|
19
|
+
export type { CompiledQuery, Dialect, Direction, FilterInput, FilterKey, FilterValue, LookupType, OrderSpec, OrderToken, QNode, QuerySetState, RelationMeta, TableMeta, WhereClause, } from './query/domain/index';
|
|
20
20
|
export { getTangoRuntime, initializeTangoRuntime, resetTangoRuntime, TangoRuntime } from './runtime/index';
|
|
21
21
|
export { atomic, UnitOfWork } from './transaction/index';
|
|
22
22
|
export type { AtomicTransaction, OnCommitOptions, SavepointOptions, SavepointResult } from './transaction/index';
|
package/dist/index.js
CHANGED
|
@@ -3,11 +3,11 @@ import { PostgresAdapter } from "./PostgresAdapter-CMiEpHya.js";
|
|
|
3
3
|
import "./SqliteClient-CjOK9-ki.js";
|
|
4
4
|
import { SqliteAdapter } from "./SqliteAdapter-CeqhyrPC.js";
|
|
5
5
|
import { AdapterRegistry, connectDB, connection_exports, getDefaultAdapterRegistry } from "./connection-B_K2ZAf7.js";
|
|
6
|
-
import { QBuilder, QueryCompiler, QuerySet, query_exports } from "./query-
|
|
6
|
+
import { QBuilder, QueryCompiler, QueryResult, QuerySet, query_exports } from "./query-FZJoSCg4.js";
|
|
7
7
|
import { TangoRuntime, getTangoRuntime, initializeTangoRuntime, resetTangoRuntime } from "./defaultRuntime-BPK9kWEW.js";
|
|
8
|
-
import { ModelManager } from "./registerModelObjects-
|
|
8
|
+
import { ModelManager } from "./registerModelObjects-C-1RbUHS.js";
|
|
9
9
|
import { manager_exports } from "./manager-C6oJ2tAF.js";
|
|
10
10
|
import { runtime_exports } from "./runtime-ByXbpVBS.js";
|
|
11
11
|
import { UnitOfWork, atomic, transaction_exports } from "./transaction-Cs0Z9tbW.js";
|
|
12
12
|
|
|
13
|
-
export { AdapterRegistry, ModelManager, PostgresAdapter, QBuilder as Q, QBuilder, QueryCompiler, QuerySet, SqliteAdapter, TangoRuntime, UnitOfWork, atomic, connectDB, connection_exports as connection, getDefaultAdapterRegistry, getTangoRuntime, initializeTangoRuntime, manager_exports as manager, query_exports as query, resetTangoRuntime, runtime_exports as runtime, transaction_exports as transaction };
|
|
13
|
+
export { AdapterRegistry, ModelManager, PostgresAdapter, QBuilder as Q, QBuilder, QueryCompiler, QueryResult, QuerySet, SqliteAdapter, TangoRuntime, UnitOfWork, atomic, connectDB, connection_exports as connection, getDefaultAdapterRegistry, getTangoRuntime, initializeTangoRuntime, manager_exports as manager, query_exports as query, resetTangoRuntime, runtime_exports as runtime, transaction_exports as transaction };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { QNode } from '../query/domain/QNode';
|
|
2
|
+
import type { FilterInput } from '../query/domain/FilterInput';
|
|
1
3
|
import type { QuerySet } from '../query/index';
|
|
2
4
|
import type { TableMeta } from '../query/domain/index';
|
|
3
5
|
/**
|
|
@@ -6,6 +8,23 @@ import type { TableMeta } from '../query/domain/index';
|
|
|
6
8
|
export interface ManagerLike<TModelRow extends Record<string, unknown>, TSourceModel = unknown> {
|
|
7
9
|
readonly meta: TableMeta;
|
|
8
10
|
query(): QuerySet<TModelRow, TModelRow, TSourceModel>;
|
|
11
|
+
all(): QuerySet<TModelRow, TModelRow, TSourceModel>;
|
|
12
|
+
getOrCreate(args: {
|
|
13
|
+
where: FilterInput<TModelRow> | QNode<TModelRow>;
|
|
14
|
+
defaults?: Partial<TModelRow>;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
record: TModelRow;
|
|
17
|
+
created: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
updateOrCreate(args: {
|
|
20
|
+
where: FilterInput<TModelRow> | QNode<TModelRow>;
|
|
21
|
+
defaults?: Partial<TModelRow>;
|
|
22
|
+
update?: Partial<TModelRow>;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
record: TModelRow;
|
|
25
|
+
created: boolean;
|
|
26
|
+
updated: boolean;
|
|
27
|
+
}>;
|
|
9
28
|
findById(id: TModelRow[keyof TModelRow]): Promise<TModelRow | null>;
|
|
10
29
|
getOrThrow(id: TModelRow[keyof TModelRow]): Promise<TModelRow>;
|
|
11
30
|
create(input: Partial<TModelRow>): Promise<TModelRow>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { QNode } from '../query/domain/QNode';
|
|
1
2
|
import type { ModelWriteHooks } from '@danceroutine/tango-schema';
|
|
2
3
|
import type { Model as SchemaModel } from '@danceroutine/tango-schema/domain';
|
|
3
|
-
import type { TableMeta } from '../query/domain/index';
|
|
4
|
+
import type { FilterInput, TableMeta } from '../query/domain/index';
|
|
4
5
|
import type { QuerySet } from '../query/index';
|
|
5
6
|
import type { TangoRuntime } from '../runtime/TangoRuntime';
|
|
6
7
|
import type { ManagerLike } from './ManagerLike';
|
|
@@ -39,7 +40,29 @@ export declare class ModelManager<TModelRow extends Record<string, unknown>, TSo
|
|
|
39
40
|
*/
|
|
40
41
|
static isModelManager<TModelRow extends Record<string, unknown>>(value: unknown): value is ModelManager<TModelRow>;
|
|
41
42
|
private static createTableMeta;
|
|
43
|
+
private static mergeCreatePayloadFromWhere;
|
|
44
|
+
private static countNonPkValues;
|
|
45
|
+
private static collectPlainFieldsFromQNode;
|
|
46
|
+
private static omitLookupKeysFromAtom;
|
|
47
|
+
private static mergeCompatiblePartials;
|
|
42
48
|
query(): QuerySet<TModelRow, TModelRow, TSourceModel>;
|
|
49
|
+
all(): QuerySet<TModelRow, TModelRow, TSourceModel>;
|
|
50
|
+
getOrCreate(args: {
|
|
51
|
+
where: FilterInput<TModelRow> | QNode<TModelRow>;
|
|
52
|
+
defaults?: Partial<TModelRow>;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
record: TModelRow;
|
|
55
|
+
created: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
updateOrCreate(args: {
|
|
58
|
+
where: FilterInput<TModelRow> | QNode<TModelRow>;
|
|
59
|
+
defaults?: Partial<TModelRow>;
|
|
60
|
+
update?: Partial<TModelRow>;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
record: TModelRow;
|
|
63
|
+
created: boolean;
|
|
64
|
+
updated: boolean;
|
|
65
|
+
}>;
|
|
43
66
|
findById(id: TModelRow[keyof TModelRow]): Promise<TModelRow | null>;
|
|
44
67
|
getOrThrow(id: TModelRow[keyof TModelRow]): Promise<TModelRow>;
|
|
45
68
|
create(input: Partial<TModelRow>): Promise<TModelRow>;
|
package/dist/manager/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "../PostgresClient-BQJZfEOT.js";
|
|
2
2
|
import "../SqliteClient-CjOK9-ki.js";
|
|
3
|
-
import "../query-
|
|
3
|
+
import "../query-FZJoSCg4.js";
|
|
4
4
|
import "../defaultRuntime-BPK9kWEW.js";
|
|
5
|
-
import { ModelManager, registerModelObjects } from "../registerModelObjects-
|
|
5
|
+
import { ModelManager, registerModelObjects } from "../registerModelObjects-C-1RbUHS.js";
|
|
6
6
|
import "../manager-C6oJ2tAF.js";
|
|
7
7
|
|
|
8
8
|
export { ModelManager, registerModelObjects };
|
package/dist/manager-C6oJ2tAF.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __export } from "./chunk-DLY2FNSh.js";
|
|
2
|
-
import { ModelManager, registerModelObjects } from "./registerModelObjects-
|
|
2
|
+
import { ModelManager, registerModelObjects } from "./registerModelObjects-C-1RbUHS.js";
|
|
3
3
|
|
|
4
4
|
//#region src/manager/index.ts
|
|
5
5
|
var manager_exports = {};
|
package/dist/query/QuerySet.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ import type { Dialect } from './domain/Dialect';
|
|
|
3
3
|
import type { QuerySetState } from './domain/QuerySetState';
|
|
4
4
|
import type { TableMeta } from './domain/TableMeta';
|
|
5
5
|
import type { QNode } from './domain/QNode';
|
|
6
|
-
import type { QueryResult } from './domain/QueryResult';
|
|
7
6
|
import type { OrderToken } from './domain/OrderToken';
|
|
8
7
|
import type { FilterInput } from './domain/FilterInput';
|
|
9
8
|
import type { CompiledQuery } from './domain/CompiledQuery';
|
|
9
|
+
import { QueryResult } from './domain/QueryResult';
|
|
10
10
|
import type { GeneratedHydratedRelationMap, GeneratedPrefetchRelatedPathKeys, GeneratedSelectRelatedPathKeys, HydratedQueryResult, ManyRelationHydrationCardinality, MaybeHydratedRelationMap, PrefetchRelatedRelations, RelationKeys, SelectRelatedRelations, SingleRelationHydrationCardinality } from './domain/RelationTyping';
|
|
11
11
|
/**
|
|
12
12
|
* Query execution seam consumed by `QuerySet`.
|
|
@@ -34,6 +34,12 @@ type ProjectedResult<TModel extends Record<string, unknown>, TKeys extends reado
|
|
|
34
34
|
* Provides a fluent API for filtering, ordering, pagination, projection, and
|
|
35
35
|
* nested relation hydration.
|
|
36
36
|
*
|
|
37
|
+
* Refinements such as `filter`, `orderBy`, `select`, and relation loaders build
|
|
38
|
+
* query state only. SQL runs when you call an evaluation method (`fetch`,
|
|
39
|
+
* `fetchOne`, `count`, `exists`, or `for await` over this queryset). After the
|
|
40
|
+
* first row-returning evaluation, this queryset instance reuses its cached
|
|
41
|
+
* materialized result on later `fetch()` or async-iteration calls.
|
|
42
|
+
*
|
|
37
43
|
* @template TModel - The full model row type used for query composition
|
|
38
44
|
* @template TBaseResult - The selected base-row shape returned by execution methods
|
|
39
45
|
* @template TSourceModel - The source Tango model used for typed relation metadata
|
|
@@ -50,16 +56,19 @@ type ProjectedResult<TModel extends Record<string, unknown>, TKeys extends reado
|
|
|
50
56
|
* .fetch();
|
|
51
57
|
* ```
|
|
52
58
|
*/
|
|
53
|
-
export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResult extends Record<string, unknown> = TModel, TSourceModel = unknown, THydrated extends Record<string, unknown> = Record<never, never>> {
|
|
59
|
+
export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResult extends Record<string, unknown> = TModel, TSourceModel = unknown, THydrated extends Record<string, unknown> = Record<never, never>> implements AsyncIterable<HydratedQueryResult<TBaseResult, THydrated>> {
|
|
60
|
+
[Symbol.asyncIterator]: () => AsyncIterator<HydratedQueryResult<TBaseResult, THydrated>>;
|
|
54
61
|
private executor;
|
|
55
62
|
private state;
|
|
56
63
|
static readonly BRAND: "tango.orm.query_set";
|
|
57
64
|
readonly __tangoBrand: typeof QuerySet.BRAND;
|
|
65
|
+
private evaluationCache?;
|
|
58
66
|
constructor(executor: QueryExecutor<TModel>, state?: QuerySetState<TModel>);
|
|
59
67
|
/**
|
|
60
68
|
* Narrow an unknown value to `QuerySet`.
|
|
61
69
|
*/
|
|
62
70
|
static isQuerySet<TModel extends Record<string, unknown>, TResult extends Record<string, unknown> = TModel>(value: unknown): value is QuerySet<TModel, TResult>;
|
|
71
|
+
private static invertOrderSpec;
|
|
63
72
|
/**
|
|
64
73
|
* Add a filter expression to the query.
|
|
65
74
|
*
|
|
@@ -113,6 +122,7 @@ export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResul
|
|
|
113
122
|
* app-local registry current.
|
|
114
123
|
*/
|
|
115
124
|
prefetchRelated<TTargetModel = undefined, const TRelationName extends RelationKeys<PrefetchRelatedRelations<TSourceModel, NoInfer<TTargetModel>>> | GeneratedPrefetchRelatedPathKeys<TSourceModel> = RelationKeys<PrefetchRelatedRelations<TSourceModel, NoInfer<TTargetModel>>> | GeneratedPrefetchRelatedPathKeys<TSourceModel>>(...rels: readonly TRelationName[]): QuerySet<TModel, TBaseResult, TSourceModel, THydrated & MaybeHydratedRelationMap<TSourceModel, PrefetchRelatedRelations<TSourceModel, NoInfer<TTargetModel>>, Extract<TRelationName, RelationKeys<PrefetchRelatedRelations<TSourceModel, NoInfer<TTargetModel>>>>, ManyRelationHydrationCardinality> & GeneratedHydratedRelationMap<TSourceModel, Extract<TRelationName, GeneratedPrefetchRelatedPathKeys<TSourceModel>>>>;
|
|
125
|
+
all(): QuerySet<TModel, TBaseResult, TSourceModel, THydrated>;
|
|
116
126
|
/**
|
|
117
127
|
* Execute the query and optionally shape each row.
|
|
118
128
|
*
|
|
@@ -123,6 +133,14 @@ export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResul
|
|
|
123
133
|
fetch<Out>(shape: QueryShapeFunction<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<QueryResult<Out>>;
|
|
124
134
|
fetch<Out>(shape: QueryShapeParser<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<QueryResult<Out>>;
|
|
125
135
|
fetch<TShape extends QueryShape<HydratedQueryResult<TBaseResult, THydrated>> | undefined>(shape: TShape): Promise<QueryResult<HydratedQueryResult<TBaseResult, THydrated> | QueryShapeOutput<HydratedQueryResult<TBaseResult, THydrated>, NonNullable<TShape>>>>;
|
|
136
|
+
/**
|
|
137
|
+
* Async iterable surface for `for await (... of queryset)`.
|
|
138
|
+
*
|
|
139
|
+
* Evaluates this queryset on first use by awaiting {@link QuerySet.fetch} without arguments, then
|
|
140
|
+
* yields each element from that {@link QueryResult}. Later async iterations over the same queryset
|
|
141
|
+
* instance reuse the cached materialized result instead of issuing another database round-trip.
|
|
142
|
+
*/
|
|
143
|
+
[Symbol.asyncIterator](): AsyncIterator<HydratedQueryResult<TBaseResult, THydrated>>;
|
|
126
144
|
/**
|
|
127
145
|
* Execute the query and return the first row, or `null`.
|
|
128
146
|
*
|
|
@@ -133,6 +151,15 @@ export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResul
|
|
|
133
151
|
fetchOne<Out>(shape: QueryShapeFunction<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
134
152
|
fetchOne<Out>(shape: QueryShapeParser<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
135
153
|
fetchOne<TShape extends QueryShape<HydratedQueryResult<TBaseResult, THydrated>> | undefined>(shape: TShape): Promise<HydratedQueryResult<TBaseResult, THydrated> | QueryShapeOutput<HydratedQueryResult<TBaseResult, THydrated>, NonNullable<TShape>> | null>;
|
|
154
|
+
first(): Promise<HydratedQueryResult<TBaseResult, THydrated> | null>;
|
|
155
|
+
first<Out>(shape: QueryShapeFunction<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
156
|
+
first<Out>(shape: QueryShapeParser<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
157
|
+
last(): Promise<HydratedQueryResult<TBaseResult, THydrated> | null>;
|
|
158
|
+
last<Out>(shape: QueryShapeFunction<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
159
|
+
last<Out>(shape: QueryShapeParser<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out | null>;
|
|
160
|
+
get(q: FilterInput<TModel> | QNode<TModel>): Promise<HydratedQueryResult<TBaseResult, THydrated>>;
|
|
161
|
+
get<Out>(q: FilterInput<TModel> | QNode<TModel>, shape: QueryShapeFunction<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out>;
|
|
162
|
+
get<Out>(q: FilterInput<TModel> | QNode<TModel>, shape: QueryShapeParser<HydratedQueryResult<TBaseResult, THydrated>, Out>): Promise<Out>;
|
|
136
163
|
/**
|
|
137
164
|
* Execute a `COUNT(*)` query for the current filtered state.
|
|
138
165
|
*/
|
|
@@ -141,7 +168,10 @@ export declare class QuerySet<TModel extends Record<string, unknown>, TBaseResul
|
|
|
141
168
|
* Return whether at least one row matches the current query state.
|
|
142
169
|
*/
|
|
143
170
|
exists(): Promise<boolean>;
|
|
144
|
-
private
|
|
171
|
+
private shapeFetchedRow;
|
|
172
|
+
private getOrCreateEvaluationCache;
|
|
173
|
+
private evaluateRows;
|
|
174
|
+
private normalizeHydratedRowsForParserShape;
|
|
145
175
|
private hydrateRows;
|
|
146
176
|
private hydrateJoinNodesForOwner;
|
|
147
177
|
private hydratePrefetchNode;
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Values materialized by {@link QuerySet.fetch}, iterable like an array plus `length`, `map`, `at`, and `toArray`.
|
|
3
|
+
*
|
|
4
|
+
* Prefer iteration or `items` over the deprecated `results` getter, which warns once per process when accessed.
|
|
5
|
+
*/
|
|
6
|
+
export declare class QueryResult<T> implements Iterable<T> {
|
|
7
|
+
/**
|
|
8
|
+
* Sync iteration over materialized rows.
|
|
9
|
+
*/
|
|
10
|
+
[Symbol.iterator]: () => Iterator<T>;
|
|
11
|
+
static readonly BRAND: "tango.orm.query_result";
|
|
12
|
+
readonly __tangoBrand: typeof QueryResult.BRAND;
|
|
13
|
+
readonly items: readonly T[];
|
|
14
|
+
constructor(items: readonly T[]);
|
|
15
|
+
/**
|
|
16
|
+
* Runtime narrowing for values that may be a plain array or a `QueryResult` instance.
|
|
17
|
+
*/
|
|
18
|
+
static isQueryResult<T>(value: unknown): value is QueryResult<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Sync iteration over materialized rows.
|
|
21
|
+
*/
|
|
22
|
+
[Symbol.iterator](): Iterator<T>;
|
|
23
|
+
/** Number of materialized rows. */
|
|
24
|
+
get length(): number;
|
|
25
|
+
/** Same as `Array#map` on the materialized rows. */
|
|
26
|
+
map<U>(callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: unknown): U[];
|
|
27
|
+
/** Indexed read with support for negative indices, like `Array#at`. */
|
|
28
|
+
at(index: number): T | undefined;
|
|
29
|
+
/** Returns a shallow copy of the materialized rows as a plain array. */
|
|
30
|
+
toArray(): T[];
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Use iteration, `length`, `map`, or `toArray()` instead.
|
|
33
|
+
*/
|
|
34
|
+
get results(): readonly T[];
|
|
4
35
|
}
|
|
@@ -11,7 +11,7 @@ export type { LookupType } from './LookupType';
|
|
|
11
11
|
export type { OrderSpec } from './OrderSpec';
|
|
12
12
|
export type { OrderToken } from './OrderToken';
|
|
13
13
|
export type { QNode } from './QNode';
|
|
14
|
-
export
|
|
14
|
+
export { QueryResult } from './QueryResult';
|
|
15
15
|
export type { QuerySetState } from './QuerySetState';
|
|
16
16
|
export type { RelationMeta } from './RelationMeta';
|
|
17
17
|
export type { ForwardSingleRelations, GeneratedHydratedRelationMap, GeneratedPrefetchRelatedPathKeys, GeneratedSelectRelatedPathKeys, HydratedQueryResult, HydratedRelationMap, ManyRelationHydrationCardinality, MaybeHydratedRelationMap, PrefetchRelatedRelations, RelationKeys, RelationHydrationCardinality, ReverseCollectionRelations, ReverseSingleRelations, SelectRelatedRelations, SingleRelationHydrationCardinality, } from './RelationTyping';
|
package/dist/query/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * as compiler from './compiler/index';
|
|
|
6
6
|
export * as domain from './domain/index';
|
|
7
7
|
export type * from './domain/index';
|
|
8
8
|
export type { TableMeta } from './domain/index';
|
|
9
|
+
export { QueryResult } from './domain/index';
|
|
9
10
|
export { QuerySet } from './QuerySet';
|
|
10
11
|
export type { QueryExecutor } from './QuerySet';
|
|
11
12
|
export { QBuilder, QBuilder as Q } from './QBuilder';
|
package/dist/query/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { QBuilder, QueryCompiler, QuerySet, compiler_exports, domain_exports } from "../query-
|
|
1
|
+
import { QBuilder, QueryCompiler, QueryResult, QuerySet, compiler_exports, domain_exports } from "../query-FZJoSCg4.js";
|
|
2
2
|
|
|
3
|
-
export { QBuilder as Q, QBuilder, QueryCompiler, QuerySet, compiler_exports as compiler, domain_exports as domain };
|
|
3
|
+
export { QBuilder as Q, QBuilder, QueryCompiler, QueryResult, QuerySet, compiler_exports as compiler, domain_exports as domain };
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { __export } from "./chunk-DLY2FNSh.js";
|
|
2
|
-
import { SqlSafetyEngine, isError } from "@danceroutine/tango-core";
|
|
2
|
+
import { MultipleObjectsReturned, NotFoundError, SqlSafetyEngine, getLogger, isError } from "@danceroutine/tango-core";
|
|
3
3
|
import { ModelRegistry } from "@danceroutine/tango-schema";
|
|
4
4
|
|
|
5
|
+
//#region src/query/domain/internal/InternalQNodeType.ts
|
|
6
|
+
const InternalQNodeType = {
|
|
7
|
+
ATOM: "atom",
|
|
8
|
+
AND: "and",
|
|
9
|
+
OR: "or",
|
|
10
|
+
NOT: "not"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
5
14
|
//#region src/query/domain/internal/InternalRelationKind.ts
|
|
6
15
|
const InternalRelationKind = {
|
|
7
16
|
HAS_MANY: "hasMany",
|
|
@@ -83,15 +92,6 @@ const InternalDialect = {
|
|
|
83
92
|
SQLITE: "sqlite"
|
|
84
93
|
};
|
|
85
94
|
|
|
86
|
-
//#endregion
|
|
87
|
-
//#region src/query/domain/internal/InternalQNodeType.ts
|
|
88
|
-
const InternalQNodeType = {
|
|
89
|
-
ATOM: "atom",
|
|
90
|
-
AND: "and",
|
|
91
|
-
OR: "or",
|
|
92
|
-
NOT: "not"
|
|
93
|
-
};
|
|
94
|
-
|
|
95
95
|
//#endregion
|
|
96
96
|
//#region src/query/domain/internal/InternalLookupType.ts
|
|
97
97
|
const InternalLookupType = {
|
|
@@ -755,11 +755,62 @@ var QueryCompiler = class QueryCompiler {
|
|
|
755
755
|
var compiler_exports = {};
|
|
756
756
|
__export(compiler_exports, { QueryCompiler: () => QueryCompiler });
|
|
757
757
|
|
|
758
|
+
//#endregion
|
|
759
|
+
//#region src/query/domain/QueryResult.ts
|
|
760
|
+
let didWarnDeprecatedResults = false;
|
|
761
|
+
var QueryResult = class QueryResult {
|
|
762
|
+
static BRAND = "tango.orm.query_result";
|
|
763
|
+
__tangoBrand = QueryResult.BRAND;
|
|
764
|
+
items;
|
|
765
|
+
constructor(items) {
|
|
766
|
+
this.items = items;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Runtime narrowing for values that may be a plain array or a `QueryResult` instance.
|
|
770
|
+
*/
|
|
771
|
+
static isQueryResult(value) {
|
|
772
|
+
return typeof value === "object" && value !== null && value.__tangoBrand === QueryResult.BRAND;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Sync iteration over materialized rows.
|
|
776
|
+
*/
|
|
777
|
+
[Symbol.iterator]() {
|
|
778
|
+
return this.items[Symbol.iterator]();
|
|
779
|
+
}
|
|
780
|
+
/** Number of materialized rows. */
|
|
781
|
+
get length() {
|
|
782
|
+
return this.items.length;
|
|
783
|
+
}
|
|
784
|
+
/** Same as `Array#map` on the materialized rows. */
|
|
785
|
+
map(callbackfn, thisArg) {
|
|
786
|
+
return this.items.map(callbackfn, thisArg);
|
|
787
|
+
}
|
|
788
|
+
/** Indexed read with support for negative indices, like `Array#at`. */
|
|
789
|
+
at(index) {
|
|
790
|
+
return this.items.at(index);
|
|
791
|
+
}
|
|
792
|
+
/** Returns a shallow copy of the materialized rows as a plain array. */
|
|
793
|
+
toArray() {
|
|
794
|
+
return [...this.items];
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* @deprecated Use iteration, `length`, `map`, or `toArray()` instead.
|
|
798
|
+
*/
|
|
799
|
+
get results() {
|
|
800
|
+
if (!didWarnDeprecatedResults) {
|
|
801
|
+
didWarnDeprecatedResults = true;
|
|
802
|
+
getLogger("tango.orm.query_result").warn("`QueryResult.results` is deprecated. Use iteration, `length`, `map`, or `toArray()` instead.");
|
|
803
|
+
}
|
|
804
|
+
return this.items;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
|
|
758
808
|
//#endregion
|
|
759
809
|
//#region src/query/domain/index.ts
|
|
760
810
|
var domain_exports = {};
|
|
761
811
|
__export(domain_exports, {
|
|
762
812
|
InternalRelationHydrationCardinality: () => InternalRelationHydrationCardinality,
|
|
813
|
+
QueryResult: () => QueryResult,
|
|
763
814
|
TableMetaFactory: () => TableMetaFactory
|
|
764
815
|
});
|
|
765
816
|
|
|
@@ -770,6 +821,19 @@ const InternalDirection = {
|
|
|
770
821
|
DESC: "desc"
|
|
771
822
|
};
|
|
772
823
|
|
|
824
|
+
//#endregion
|
|
825
|
+
//#region src/query/internal/isQNodeLike.ts
|
|
826
|
+
function isQNodeLike(value) {
|
|
827
|
+
if (typeof value !== "object" || value === null || "__tangoBrand" in value) return false;
|
|
828
|
+
switch (value.kind) {
|
|
829
|
+
case InternalQNodeType.ATOM: return "where" in value;
|
|
830
|
+
case InternalQNodeType.AND:
|
|
831
|
+
case InternalQNodeType.OR: return Array.isArray(value.nodes);
|
|
832
|
+
case InternalQNodeType.NOT: return "node" in value;
|
|
833
|
+
default: return false;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
773
837
|
//#endregion
|
|
774
838
|
//#region src/query/QBuilder.ts
|
|
775
839
|
var QBuilder = class QBuilder {
|
|
@@ -809,7 +873,7 @@ var QBuilder = class QBuilder {
|
|
|
809
873
|
};
|
|
810
874
|
}
|
|
811
875
|
static wrapNode(input) {
|
|
812
|
-
if (input
|
|
876
|
+
if (isQNodeLike(input)) return input;
|
|
813
877
|
return {
|
|
814
878
|
kind: InternalQNodeType.ATOM,
|
|
815
879
|
where: input
|
|
@@ -822,6 +886,7 @@ var QBuilder = class QBuilder {
|
|
|
822
886
|
var QuerySet = class QuerySet {
|
|
823
887
|
static BRAND = "tango.orm.query_set";
|
|
824
888
|
__tangoBrand = QuerySet.BRAND;
|
|
889
|
+
evaluationCache;
|
|
825
890
|
constructor(executor, state = {}) {
|
|
826
891
|
this.executor = executor;
|
|
827
892
|
this.state = state;
|
|
@@ -832,13 +897,20 @@ var QuerySet = class QuerySet {
|
|
|
832
897
|
static isQuerySet(value) {
|
|
833
898
|
return typeof value === "object" && value !== null && value.__tangoBrand === QuerySet.BRAND;
|
|
834
899
|
}
|
|
900
|
+
static invertOrderSpec(order) {
|
|
901
|
+
if (!order?.length) return [];
|
|
902
|
+
return order.map((spec) => ({
|
|
903
|
+
by: spec.by,
|
|
904
|
+
dir: spec.dir === InternalDirection.ASC ? InternalDirection.DESC : InternalDirection.ASC
|
|
905
|
+
}));
|
|
906
|
+
}
|
|
835
907
|
/**
|
|
836
908
|
* Add a filter expression to the query.
|
|
837
909
|
*
|
|
838
910
|
* Multiple `filter()` calls are composed with `AND`.
|
|
839
911
|
*/
|
|
840
912
|
filter(q) {
|
|
841
|
-
const wrapped = q
|
|
913
|
+
const wrapped = isQNodeLike(q) ? q : {
|
|
842
914
|
kind: InternalQNodeType.ATOM,
|
|
843
915
|
where: q
|
|
844
916
|
};
|
|
@@ -854,7 +926,7 @@ var QuerySet = class QuerySet {
|
|
|
854
926
|
* Exclusions are translated to `NOT (...)` predicates.
|
|
855
927
|
*/
|
|
856
928
|
exclude(q) {
|
|
857
|
-
const wrapped = q
|
|
929
|
+
const wrapped = isQNodeLike(q) ? q : {
|
|
858
930
|
kind: InternalQNodeType.ATOM,
|
|
859
931
|
where: q
|
|
860
932
|
};
|
|
@@ -937,23 +1009,61 @@ var QuerySet = class QuerySet {
|
|
|
937
1009
|
prefetchRelated: [...rels]
|
|
938
1010
|
});
|
|
939
1011
|
}
|
|
1012
|
+
all() {
|
|
1013
|
+
return new QuerySet(this.executor, { ...this.state });
|
|
1014
|
+
}
|
|
940
1015
|
async fetch(shape) {
|
|
941
|
-
const
|
|
942
|
-
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
1016
|
+
const baseResult = await this.getOrCreateEvaluationCache();
|
|
1017
|
+
if (!shape) return baseResult;
|
|
1018
|
+
const results = typeof shape === "function" ? baseResult.items.map(shape) : this.normalizeHydratedRowsForParserShape(baseResult.items).map((row) => shape.parse(row));
|
|
1019
|
+
return new QueryResult(results);
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Async iterable surface for `for await (... of queryset)`.
|
|
1023
|
+
*
|
|
1024
|
+
* Evaluates this queryset on first use by awaiting {@link QuerySet.fetch} without arguments, then
|
|
1025
|
+
* yields each element from that {@link QueryResult}. Later async iterations over the same queryset
|
|
1026
|
+
* instance reuse the cached materialized result instead of issuing another database round-trip.
|
|
1027
|
+
*/
|
|
1028
|
+
async *[Symbol.asyncIterator]() {
|
|
1029
|
+
const result = await this.fetch();
|
|
1030
|
+
for (const row of result) yield row;
|
|
952
1031
|
}
|
|
953
1032
|
async fetchOne(shape) {
|
|
954
1033
|
const limited = this.limit(1);
|
|
955
1034
|
const result = !shape ? await limited.fetch() : typeof shape === "function" ? await limited.fetch(shape) : await limited.fetch(shape);
|
|
956
|
-
|
|
1035
|
+
for (const row of result) return row;
|
|
1036
|
+
return null;
|
|
1037
|
+
}
|
|
1038
|
+
async first(shape) {
|
|
1039
|
+
return this.fetchOne(shape);
|
|
1040
|
+
}
|
|
1041
|
+
async last(shape) {
|
|
1042
|
+
if (this.state.limit !== undefined || this.state.offset !== undefined) {
|
|
1043
|
+
const page = await this.fetch();
|
|
1044
|
+
const row = page.at(-1);
|
|
1045
|
+
if (!row) return null;
|
|
1046
|
+
return this.shapeFetchedRow(row, shape);
|
|
1047
|
+
}
|
|
1048
|
+
const invertedOrder = QuerySet.invertOrderSpec(this.state.order);
|
|
1049
|
+
const effectiveOrder = invertedOrder.length > 0 ? invertedOrder : [{
|
|
1050
|
+
by: this.executor.meta.pk,
|
|
1051
|
+
dir: InternalDirection.DESC
|
|
1052
|
+
}];
|
|
1053
|
+
const qs = new QuerySet(this.executor, {
|
|
1054
|
+
...this.state,
|
|
1055
|
+
order: effectiveOrder
|
|
1056
|
+
});
|
|
1057
|
+
return qs.limit(1).fetchOne(shape);
|
|
1058
|
+
}
|
|
1059
|
+
async get(q, shape) {
|
|
1060
|
+
const limited = this.filter(q).limit(2);
|
|
1061
|
+
const page = await limited.fetch();
|
|
1062
|
+
const rows = page.items;
|
|
1063
|
+
const count = rows.length;
|
|
1064
|
+
if (count === 0) throw new NotFoundError(`${this.executor.meta.table}: no matching record`);
|
|
1065
|
+
if (count > 1) throw new MultipleObjectsReturned(`${this.executor.meta.table}: more than one matching record`);
|
|
1066
|
+
return this.shapeFetchedRow(rows[0], shape);
|
|
957
1067
|
}
|
|
958
1068
|
/**
|
|
959
1069
|
* Execute a `COUNT(*)` query for the current filtered state.
|
|
@@ -972,10 +1082,31 @@ var QuerySet = class QuerySet {
|
|
|
972
1082
|
const count = await this.count();
|
|
973
1083
|
return count > 0;
|
|
974
1084
|
}
|
|
975
|
-
|
|
976
|
-
if (!shape
|
|
1085
|
+
shapeFetchedRow(row, shape) {
|
|
1086
|
+
if (!shape) return row;
|
|
1087
|
+
if (typeof shape === "function") return shape(row);
|
|
1088
|
+
const normalizedRow = this.normalizeHydratedRowsForParserShape([row])[0] ?? row;
|
|
1089
|
+
return shape.parse(normalizedRow);
|
|
1090
|
+
}
|
|
1091
|
+
getOrCreateEvaluationCache() {
|
|
1092
|
+
if (!this.evaluationCache) this.evaluationCache = this.evaluateRows().catch((error) => {
|
|
1093
|
+
this.evaluationCache = undefined;
|
|
1094
|
+
throw error;
|
|
1095
|
+
});
|
|
1096
|
+
return this.evaluationCache;
|
|
1097
|
+
}
|
|
1098
|
+
async evaluateRows() {
|
|
1099
|
+
const compiler = new QueryCompiler(this.executor.meta, this.executor.dialect);
|
|
1100
|
+
const compiled = compiler.compile(this.state);
|
|
1101
|
+
const rows = await this.executor.run(compiled);
|
|
1102
|
+
const hydratedRows = await this.hydrateRows(rows, compiled);
|
|
1103
|
+
const projectedRows = hydratedRows;
|
|
1104
|
+
return new QueryResult(projectedRows);
|
|
1105
|
+
}
|
|
1106
|
+
normalizeHydratedRowsForParserShape(rows) {
|
|
1107
|
+
if (this.executor.dialect !== InternalDialect.SQLITE) return [...rows];
|
|
977
1108
|
const booleanColumns = Object.entries(this.executor.meta.columns).filter(([, value]) => this.isBooleanColumnType(value)).map(([column]) => column);
|
|
978
|
-
if (booleanColumns.length === 0) return rows;
|
|
1109
|
+
if (booleanColumns.length === 0) return [...rows];
|
|
979
1110
|
return rows.map((row) => this.normalizeBooleanColumns(row, booleanColumns));
|
|
980
1111
|
}
|
|
981
1112
|
async hydrateRows(rows, compiled) {
|
|
@@ -1115,11 +1246,12 @@ __export(query_exports, {
|
|
|
1115
1246
|
Q: () => QBuilder,
|
|
1116
1247
|
QBuilder: () => QBuilder,
|
|
1117
1248
|
QueryCompiler: () => QueryCompiler,
|
|
1249
|
+
QueryResult: () => QueryResult,
|
|
1118
1250
|
QuerySet: () => QuerySet,
|
|
1119
1251
|
compiler: () => compiler_exports,
|
|
1120
1252
|
domain: () => domain_exports
|
|
1121
1253
|
});
|
|
1122
1254
|
|
|
1123
1255
|
//#endregion
|
|
1124
|
-
export { OrmSqlSafetyAdapter, QBuilder, QueryCompiler, QuerySet, TableMetaFactory, compiler_exports, domain_exports, query_exports };
|
|
1125
|
-
//# sourceMappingURL=query-
|
|
1256
|
+
export { InternalQNodeType, OrmSqlSafetyAdapter, QBuilder, QueryCompiler, QueryResult, QuerySet, TableMetaFactory, compiler_exports, domain_exports, isQNodeLike, query_exports };
|
|
1257
|
+
//# sourceMappingURL=query-FZJoSCg4.js.map
|