@prisma-next/sql-orm-client 0.7.0 → 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/dist/index.d.mts +70 -17
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +210 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -21
- package/src/collection.ts +262 -56
- package/src/grouped-collection.ts +34 -8
- package/src/query-plan-meta.ts +57 -3
- package/src/query-plan-select.ts +4 -3
- package/src/query-plan.ts +1 -0
- package/src/types.ts +10 -0
package/src/query-plan-meta.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Contract, PlanMeta } from '@prisma-next/contract/types';
|
|
2
|
+
import type { AnnotationValue, OperationKind } from '@prisma-next/framework-components/runtime';
|
|
2
3
|
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
3
4
|
import { type AnyQueryAst, collectOrderedParamRefs } from '@prisma-next/sql-relational-core/ast';
|
|
4
5
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
6
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
5
7
|
|
|
6
8
|
export function deriveParamsFromAst(ast: AnyQueryAst): {
|
|
7
9
|
params: unknown[];
|
|
@@ -19,12 +21,20 @@ export function resolveTableColumns(contract: Contract<SqlStorage>, tableName: s
|
|
|
19
21
|
return Object.keys(table.columns);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
export function buildOrmPlanMeta(
|
|
24
|
+
export function buildOrmPlanMeta(
|
|
25
|
+
contract: Contract<SqlStorage>,
|
|
26
|
+
annotations?: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>,
|
|
27
|
+
): PlanMeta {
|
|
28
|
+
const annotationRecord =
|
|
29
|
+
annotations !== undefined && annotations.size > 0
|
|
30
|
+
? Object.freeze(Object.fromEntries(annotations))
|
|
31
|
+
: undefined;
|
|
23
32
|
return {
|
|
24
33
|
target: contract.target,
|
|
25
34
|
targetFamily: contract.targetFamily,
|
|
26
35
|
storageHash: contract.storage.storageHash,
|
|
27
|
-
...(
|
|
36
|
+
...ifDefined('profileHash', contract.profileHash),
|
|
37
|
+
...ifDefined('annotations', annotationRecord),
|
|
28
38
|
lane: 'orm-client',
|
|
29
39
|
};
|
|
30
40
|
}
|
|
@@ -33,10 +43,54 @@ export function buildOrmQueryPlan<Row>(
|
|
|
33
43
|
contract: Contract<SqlStorage>,
|
|
34
44
|
ast: AnyQueryAst,
|
|
35
45
|
params: readonly unknown[],
|
|
46
|
+
annotations?: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>,
|
|
36
47
|
): SqlQueryPlan<Row> {
|
|
37
48
|
return Object.freeze({
|
|
38
49
|
ast,
|
|
39
50
|
params: [...params],
|
|
40
|
-
meta: buildOrmPlanMeta(contract),
|
|
51
|
+
meta: buildOrmPlanMeta(contract, annotations),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Merges annotations into an existing `SqlQueryPlan`'s
|
|
57
|
+
* `meta.annotations` and returns a new frozen plan.
|
|
58
|
+
*
|
|
59
|
+
* Used by the ORM dispatch path to attach terminal-call annotations to
|
|
60
|
+
* plans produced by mutation compile functions (which don't take
|
|
61
|
+
* annotations as parameters). Reads compile through `compileSelect`-
|
|
62
|
+
* family functions that pass `state.annotations` directly to
|
|
63
|
+
* `buildOrmQueryPlan`; this helper is the alternate path for write
|
|
64
|
+
* terminals where annotations arrive at the call site, not via state.
|
|
65
|
+
*
|
|
66
|
+
* Returns the input plan unchanged when `annotations` is undefined
|
|
67
|
+
* or empty. Reserved framework namespaces (`codecs`, `limit`) on the
|
|
68
|
+
* input plan win over caller-supplied entries under the same key —
|
|
69
|
+
* see the reserved-namespace policy on `defineAnnotation`.
|
|
70
|
+
*/
|
|
71
|
+
export function mergeAnnotations<Row>(
|
|
72
|
+
plan: SqlQueryPlan<Row>,
|
|
73
|
+
annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> | undefined,
|
|
74
|
+
): SqlQueryPlan<Row> {
|
|
75
|
+
if (annotations === undefined || annotations.size === 0) {
|
|
76
|
+
return plan;
|
|
77
|
+
}
|
|
78
|
+
const callerEntries: Record<string, AnnotationValue<unknown, OperationKind>> = {};
|
|
79
|
+
for (const [namespace, value] of annotations) {
|
|
80
|
+
callerEntries[namespace] = value;
|
|
81
|
+
}
|
|
82
|
+
// Caller-supplied annotations go first so framework-reserved keys on
|
|
83
|
+
// the existing plan (codecs, limit) override any collision under the
|
|
84
|
+
// same namespace.
|
|
85
|
+
const mergedAnnotations = Object.freeze({
|
|
86
|
+
...callerEntries,
|
|
87
|
+
...(plan.meta.annotations ?? {}),
|
|
88
|
+
});
|
|
89
|
+
return Object.freeze({
|
|
90
|
+
...plan,
|
|
91
|
+
meta: Object.freeze({
|
|
92
|
+
...plan.meta,
|
|
93
|
+
annotations: mergedAnnotations,
|
|
94
|
+
}),
|
|
41
95
|
});
|
|
42
96
|
}
|
package/src/query-plan-select.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '@prisma-next/sql-relational-core/ast';
|
|
24
24
|
import { codecRefForStorageColumn } from '@prisma-next/sql-relational-core/codec-descriptor-registry';
|
|
25
25
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
26
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
26
27
|
import {
|
|
27
28
|
type PolymorphismInfo,
|
|
28
29
|
resolvePolymorphismInfo,
|
|
@@ -451,7 +452,7 @@ export function compileSelect(
|
|
|
451
452
|
);
|
|
452
453
|
|
|
453
454
|
const { params } = deriveParamsFromAst(ast);
|
|
454
|
-
return buildOrmQueryPlan(contract, ast, params);
|
|
455
|
+
return buildOrmQueryPlan(contract, ast, params, state.annotations);
|
|
455
456
|
}
|
|
456
457
|
|
|
457
458
|
export function compileRelationSelect(
|
|
@@ -522,10 +523,10 @@ export function compileSelectWithIncludeStrategy(
|
|
|
522
523
|
{
|
|
523
524
|
joins: includeJoins,
|
|
524
525
|
includeProjection,
|
|
525
|
-
...(
|
|
526
|
+
...ifDefined('where', topLevelWhere),
|
|
526
527
|
},
|
|
527
528
|
);
|
|
528
529
|
|
|
529
530
|
const { params } = deriveParamsFromAst(ast);
|
|
530
|
-
return buildOrmQueryPlan(contract, ast, params);
|
|
531
|
+
return buildOrmQueryPlan(contract, ast, params, state.annotations);
|
|
531
532
|
}
|
package/src/query-plan.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
+
import type { AnnotationValue, OperationKind } from '@prisma-next/framework-components/runtime';
|
|
2
3
|
import type {
|
|
3
4
|
ExtractCodecTypes,
|
|
4
5
|
ExtractQueryOperationTypes,
|
|
@@ -72,6 +73,14 @@ export interface CollectionState {
|
|
|
72
73
|
readonly limit: number | undefined;
|
|
73
74
|
readonly offset: number | undefined;
|
|
74
75
|
readonly variantName: string | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Annotations attached to this query at terminal-call time.
|
|
78
|
+
* Populated transiently by terminal methods (`first`, `all`, `create`,
|
|
79
|
+
* etc.) just before dispatch — `Collection` itself has no chainable
|
|
80
|
+
* `.annotate()`. Stored as a `Map<namespace, AnnotationValue>` so
|
|
81
|
+
* duplicate namespaces last-write-win. Empty on a fresh state.
|
|
82
|
+
*/
|
|
83
|
+
readonly annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
|
|
75
84
|
}
|
|
76
85
|
|
|
77
86
|
export function emptyState(): CollectionState {
|
|
@@ -86,6 +95,7 @@ export function emptyState(): CollectionState {
|
|
|
86
95
|
limit: undefined,
|
|
87
96
|
offset: undefined,
|
|
88
97
|
variantName: undefined,
|
|
98
|
+
annotations: new Map(),
|
|
89
99
|
};
|
|
90
100
|
}
|
|
91
101
|
|