@pothos/plugin-drizzle 0.18.1 → 0.19.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/CHANGELOG.md +345 -0
- package/README.md +784 -221
- package/dts/connection-helpers.d.ts +18 -8
- package/dts/connection-helpers.d.ts.map +1 -1
- package/dts/drizzle-field-builder.d.ts +4 -11
- package/dts/drizzle-field-builder.d.ts.map +1 -1
- package/dts/global-types.d.ts.map +1 -1
- package/dts/index.d.ts.map +1 -1
- package/dts/model-loader.d.ts +18 -17
- package/dts/model-loader.d.ts.map +1 -1
- package/dts/types.d.ts +80 -20
- package/dts/types.d.ts.map +1 -1
- package/dts/utils/adapter.d.ts +39 -0
- package/dts/utils/adapter.d.ts.map +1 -0
- package/dts/utils/await-selections.d.ts +12 -0
- package/dts/utils/await-selections.d.ts.map +1 -0
- package/dts/utils/config.d.ts +23 -3
- package/dts/utils/config.d.ts.map +1 -1
- package/dts/utils/cursors.d.ts +6 -6
- package/dts/utils/cursors.d.ts.map +1 -1
- package/dts/utils/map-query.d.ts +22 -21
- package/dts/utils/map-query.d.ts.map +1 -1
- package/dts/utils/path-info.d.ts +13 -0
- package/dts/utils/path-info.d.ts.map +1 -0
- package/dts/utils/relation-filter.d.ts +48 -0
- package/dts/utils/relation-filter.d.ts.map +1 -0
- package/dts/utils/selections.d.ts +2 -21
- package/dts/utils/selections.d.ts.map +1 -1
- package/esm/connection-helpers.d.ts +18 -8
- package/esm/connection-helpers.d.ts.map +1 -1
- package/esm/connection-helpers.js +52 -19
- package/esm/connection-helpers.js.map +1 -1
- package/esm/drizzle-field-builder.d.ts +4 -11
- package/esm/drizzle-field-builder.d.ts.map +1 -1
- package/esm/drizzle-field-builder.js +138 -96
- package/esm/drizzle-field-builder.js.map +1 -1
- package/esm/field-builder.js +61 -47
- package/esm/field-builder.js.map +1 -1
- package/esm/global-types.d.ts.map +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +37 -61
- package/esm/index.js.map +1 -1
- package/esm/model-loader.d.ts +18 -17
- package/esm/model-loader.d.ts.map +1 -1
- package/esm/model-loader.js +76 -45
- package/esm/model-loader.js.map +1 -1
- package/esm/schema-builder.js +40 -149
- package/esm/schema-builder.js.map +1 -1
- package/esm/types.d.ts +80 -20
- package/esm/types.d.ts.map +1 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/adapter.d.ts +39 -0
- package/esm/utils/adapter.d.ts.map +1 -0
- package/esm/utils/adapter.js +137 -0
- package/esm/utils/adapter.js.map +1 -0
- package/esm/utils/await-selections.d.ts +12 -0
- package/esm/utils/await-selections.d.ts.map +1 -0
- package/esm/utils/await-selections.js +19 -0
- package/esm/utils/await-selections.js.map +1 -0
- package/esm/utils/config.d.ts +23 -3
- package/esm/utils/config.d.ts.map +1 -1
- package/esm/utils/config.js +1 -4
- package/esm/utils/config.js.map +1 -1
- package/esm/utils/cursors.d.ts +6 -6
- package/esm/utils/cursors.d.ts.map +1 -1
- package/esm/utils/cursors.js +55 -90
- package/esm/utils/cursors.js.map +1 -1
- package/esm/utils/map-query.d.ts +22 -21
- package/esm/utils/map-query.d.ts.map +1 -1
- package/esm/utils/map-query.js +40 -354
- package/esm/utils/map-query.js.map +1 -1
- package/esm/utils/path-info.d.ts +13 -0
- package/esm/utils/path-info.d.ts.map +1 -0
- package/esm/utils/path-info.js +37 -0
- package/esm/utils/path-info.js.map +1 -0
- package/esm/utils/relation-filter.d.ts +48 -0
- package/esm/utils/relation-filter.d.ts.map +1 -0
- package/esm/utils/relation-filter.js +92 -0
- package/esm/utils/relation-filter.js.map +1 -0
- package/esm/utils/selections.d.ts +2 -21
- package/esm/utils/selections.d.ts.map +1 -1
- package/esm/utils/selections.js +1 -133
- package/esm/utils/selections.js.map +1 -1
- package/lib/connection-helpers.js +51 -18
- package/lib/connection-helpers.js.map +1 -1
- package/lib/drizzle-field-builder.js +136 -94
- package/lib/drizzle-field-builder.js.map +1 -1
- package/lib/field-builder.js +58 -44
- package/lib/field-builder.js.map +1 -1
- package/lib/index.js +36 -60
- package/lib/index.js.map +1 -1
- package/lib/model-loader.js +76 -45
- package/lib/model-loader.js.map +1 -1
- package/lib/schema-builder.js +40 -149
- package/lib/schema-builder.js.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/adapter.js +147 -0
- package/lib/utils/adapter.js.map +1 -0
- package/lib/utils/await-selections.js +20 -0
- package/lib/utils/await-selections.js.map +1 -0
- package/lib/utils/config.js +1 -4
- package/lib/utils/config.js.map +1 -1
- package/lib/utils/cursors.js +47 -88
- package/lib/utils/cursors.js.map +1 -1
- package/lib/utils/map-query.js +28 -359
- package/lib/utils/map-query.js.map +1 -1
- package/lib/utils/path-info.js +39 -0
- package/lib/utils/path-info.js.map +1 -0
- package/lib/utils/relation-filter.js +91 -0
- package/lib/utils/relation-filter.js.map +1 -0
- package/lib/utils/selections.js +3 -158
- package/lib/utils/selections.js.map +1 -1
- package/package.json +8 -6
- package/src/connection-helpers.ts +167 -53
- package/src/drizzle-field-builder.ts +296 -176
- package/src/field-builder.ts +110 -77
- package/src/global-types.ts +0 -32
- package/src/index.ts +42 -68
- package/src/model-loader.ts +110 -71
- package/src/schema-builder.ts +76 -169
- package/src/types.ts +175 -44
- package/src/utils/adapter.ts +197 -0
- package/src/utils/await-selections.ts +31 -0
- package/src/utils/config.ts +1 -5
- package/src/utils/cursors.ts +53 -81
- package/src/utils/map-query.ts +51 -734
- package/src/utils/path-info.ts +40 -0
- package/src/utils/relation-filter.ts +185 -0
- package/src/utils/selections.ts +2 -207
- package/dts/utils/deep-equal.d.ts +0 -2
- package/dts/utils/deep-equal.d.ts.map +0 -1
- package/dts/utils/drizzle-graphql.d.ts +0 -2
- package/dts/utils/drizzle-graphql.d.ts.map +0 -1
- package/dts/utils/loader-map.d.ts +0 -11
- package/dts/utils/loader-map.d.ts.map +0 -1
- package/dts/utils/usage.d.ts +0 -5
- package/dts/utils/usage.d.ts.map +0 -1
- package/esm/utils/deep-equal.d.ts +0 -2
- package/esm/utils/deep-equal.d.ts.map +0 -1
- package/esm/utils/deep-equal.js +0 -45
- package/esm/utils/deep-equal.js.map +0 -1
- package/esm/utils/drizzle-graphql.d.ts +0 -2
- package/esm/utils/drizzle-graphql.d.ts.map +0 -1
- package/esm/utils/drizzle-graphql.js +0 -232
- package/esm/utils/drizzle-graphql.js.map +0 -1
- package/esm/utils/loader-map.d.ts +0 -11
- package/esm/utils/loader-map.d.ts.map +0 -1
- package/esm/utils/loader-map.js +0 -35
- package/esm/utils/loader-map.js.map +0 -1
- package/esm/utils/usage.d.ts +0 -5
- package/esm/utils/usage.d.ts.map +0 -1
- package/esm/utils/usage.js +0 -59
- package/esm/utils/usage.js.map +0 -1
- package/lib/utils/deep-equal.js +0 -55
- package/lib/utils/deep-equal.js.map +0 -1
- package/lib/utils/drizzle-graphql.js +0 -236
- package/lib/utils/drizzle-graphql.js.map +0 -1
- package/lib/utils/loader-map.js +0 -56
- package/lib/utils/loader-map.js.map +0 -1
- package/lib/utils/usage.js +0 -83
- package/lib/utils/usage.js.map +0 -1
- package/src/utils/deep-equal.ts +0 -57
- package/src/utils/drizzle-graphql.ts +0 -274
- package/src/utils/loader-map.ts +0 -49
- package/src/utils/usage.ts +0 -62
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Position } from '@pothos/selection-mapper';
|
|
2
|
+
import { type GraphQLOutputType, isListType, isNonNullType } from 'graphql';
|
|
3
|
+
import type { FieldPathInfo, PathInfo } from '../types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The public `PathInfo` of a position: `path` as `Type.field` from the field the query was
|
|
7
|
+
* planned for down to the field being planned, and one segment per step with the alias the
|
|
8
|
+
* document used and whether the field is a list.
|
|
9
|
+
*
|
|
10
|
+
* The walker hands out positions, which are links rather than paths; this is the only place the
|
|
11
|
+
* chain is walked, and it is walked only when a `query` callback or a `select` function actually
|
|
12
|
+
* wants one. A field whose query is a plain object never builds either array.
|
|
13
|
+
*/
|
|
14
|
+
export function pathInfoFor(position: Position | undefined): PathInfo | undefined {
|
|
15
|
+
if (!position) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const path: string[] = [];
|
|
20
|
+
const segments: FieldPathInfo[] = [];
|
|
21
|
+
|
|
22
|
+
for (let at: Position | undefined = position; at; at = at.parent) {
|
|
23
|
+
const field = at.node.name.value;
|
|
24
|
+
|
|
25
|
+
path.push(`${at.type.name}.${field}`);
|
|
26
|
+
segments.push({
|
|
27
|
+
field,
|
|
28
|
+
alias: at.node.alias?.value ?? field,
|
|
29
|
+
parentType: at.type.name,
|
|
30
|
+
isList: isListField(at.field.type),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { path: path.reverse(), segments: segments.reverse() };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** A list field, whether or not the list itself is non-null (`[Post!]!`). */
|
|
38
|
+
function isListField(type: GraphQLOutputType) {
|
|
39
|
+
return isListType(type) || (isNonNullType(type) && isListType(type.ofType));
|
|
40
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
aliasedTable,
|
|
3
|
+
aliasedTableColumn,
|
|
4
|
+
and,
|
|
5
|
+
type Column,
|
|
6
|
+
count,
|
|
7
|
+
countDistinct,
|
|
8
|
+
exists,
|
|
9
|
+
getTableName,
|
|
10
|
+
inArray,
|
|
11
|
+
is,
|
|
12
|
+
type Relation,
|
|
13
|
+
relationToSQL,
|
|
14
|
+
type SQL,
|
|
15
|
+
type SQLWrapper,
|
|
16
|
+
sql,
|
|
17
|
+
type Table,
|
|
18
|
+
} from 'drizzle-orm';
|
|
19
|
+
import { SQLiteTable } from 'drizzle-orm/sqlite-core';
|
|
20
|
+
|
|
21
|
+
import type { DrizzleClient } from '../types.js';
|
|
22
|
+
|
|
23
|
+
/** The public client's SQL construction capability. */
|
|
24
|
+
export type RelationQueryBuilder = Pick<DrizzleClient, 'select'>;
|
|
25
|
+
|
|
26
|
+
export interface RelationFilter {
|
|
27
|
+
/**
|
|
28
|
+
* A predicate over the target table alone, for the places where only the target table is in
|
|
29
|
+
* scope: a `where` handed to a user `select`, or a count that selects from the target table.
|
|
30
|
+
* SQLite many-to-many relations with a non-null unique target key project identities through
|
|
31
|
+
* Drizzle's join. Other cases use an `exists` over the junction.
|
|
32
|
+
*/
|
|
33
|
+
filter: SQL;
|
|
34
|
+
/**
|
|
35
|
+
* Counts the rows the relation yields, as an expression for the surrounding query to select.
|
|
36
|
+
* A many-to-many relation joins the junction table in, so the count matches the rows the
|
|
37
|
+
* relational query builder returns for the same relation, junction duplicates included.
|
|
38
|
+
*
|
|
39
|
+
* `where` is the predicate the page query was given, and it goes ahead of the relation's own
|
|
40
|
+
* predicate because that is the order the relational query builder combines the two in. The
|
|
41
|
+
* count then repeats the page query's `where` verbatim, minus the limit and keyset clauses.
|
|
42
|
+
*/
|
|
43
|
+
countRows: (where?: SQL) => SQL<number>;
|
|
44
|
+
/**
|
|
45
|
+
* Counts the distinct target rows the relation reaches, for the callers that count a related
|
|
46
|
+
* row once however many junction rows lead to it. `key` identifies a target row, so it has to
|
|
47
|
+
* be a single column the database guarantees is unique and non-null.
|
|
48
|
+
*
|
|
49
|
+
* This counts off the junction rather than counting the target table filtered by `filter`,
|
|
50
|
+
* which says the same thing the long way round: the join reads the junction rows the parent
|
|
51
|
+
* reaches and stops, where the filter reads the same rows and then looks every key it found
|
|
52
|
+
* back up in the target table.
|
|
53
|
+
*/
|
|
54
|
+
countDistinctRows: (key: Column, where?: SQL) => SQL<number>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// `select 1`, for an `exists` that only has to find a row.
|
|
58
|
+
const one = { one: sql`1` };
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The parent-to-child SQL for one relation, built by drizzle so the plugin agrees with the
|
|
62
|
+
* relational query builder on what "related" means: `through` (many-to-many), the relation's own
|
|
63
|
+
* `where`, and a reversed relation's inherited `where` all come from drizzle rather than from a
|
|
64
|
+
* join reassembled here out of source and target columns.
|
|
65
|
+
*
|
|
66
|
+
* Both the join and its restrictions come from `relationToSQL`, including when the target is
|
|
67
|
+
* aliased for the identity lookup. No junction columns or comparisons are reconstructed here.
|
|
68
|
+
*
|
|
69
|
+
* `parentTable` is the parent as it appears in the surrounding query, so the aliased table when
|
|
70
|
+
* the query builder aliased it.
|
|
71
|
+
*/
|
|
72
|
+
export function buildRelationFilter(
|
|
73
|
+
client: RelationQueryBuilder,
|
|
74
|
+
relation: Relation,
|
|
75
|
+
parentTable: Table,
|
|
76
|
+
targetKey?: Column[],
|
|
77
|
+
): RelationFilter {
|
|
78
|
+
const targetTable = relation.targetTable as Table;
|
|
79
|
+
const throughTable = relation.throughTable as Table | undefined;
|
|
80
|
+
// `filter` correlates the parent to the target, or to the junction table when there is one, in
|
|
81
|
+
// which case `joinCondition` is what carries the junction the rest of the way to the target.
|
|
82
|
+
const { filter, joinCondition } = relationToSQL(
|
|
83
|
+
relation,
|
|
84
|
+
parentTable,
|
|
85
|
+
targetTable,
|
|
86
|
+
throughTable,
|
|
87
|
+
) as { filter: SQL; joinCondition?: SQL };
|
|
88
|
+
|
|
89
|
+
if (!throughTable || !joinCondition) {
|
|
90
|
+
// Without a junction table every related row is a distinct target row, so the two counts are
|
|
91
|
+
// the same query.
|
|
92
|
+
const countRows = (where?: SQL) =>
|
|
93
|
+
countOf(client.select(countStar()).from(targetTable).where(and(where, filter)));
|
|
94
|
+
|
|
95
|
+
return { filter, countRows, countDistinctRows: (_key, where) => countRows(where) };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const relatedRows = (aggregate: Record<string, SQL>, where?: SQL) =>
|
|
99
|
+
countOf(
|
|
100
|
+
client
|
|
101
|
+
.select(aggregate)
|
|
102
|
+
.from(targetTable)
|
|
103
|
+
.innerJoin(throughTable, joinCondition)
|
|
104
|
+
.where(and(where, filter)),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
// SQLite needs the identity lookup to avoid target scans. PostgreSQL can plan EXISTS as
|
|
109
|
+
// a semijoin; projecting identities adds a target join its planner may not eliminate.
|
|
110
|
+
filter:
|
|
111
|
+
targetKey?.length && is(targetTable, SQLiteTable)
|
|
112
|
+
? targetIdentityInRelation(
|
|
113
|
+
client,
|
|
114
|
+
relation,
|
|
115
|
+
parentTable,
|
|
116
|
+
targetTable,
|
|
117
|
+
throughTable,
|
|
118
|
+
targetKey,
|
|
119
|
+
)
|
|
120
|
+
: exists(client.select(one).from(throughTable).where(and(filter, joinCondition))),
|
|
121
|
+
countRows: (where) => relatedRows(countStar(), where),
|
|
122
|
+
countDistinctRows: (key, where) => relatedRows({ count: countDistinct(key) }, where),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Project a non-null unique target key through the original relation join, then compare that
|
|
128
|
+
* key with itself. Comparing the target key directly with a junction column would change
|
|
129
|
+
* SQLite's collation precedence. Keeping the join also handles composite relation keys and
|
|
130
|
+
* excludes null junction keys without special truth-table guards.
|
|
131
|
+
*
|
|
132
|
+
* `key` must be a database-enforced unique constraint whose columns are all NOT NULL. That
|
|
133
|
+
* makes membership identify exactly one target row and keeps negation two-valued. SQLite can
|
|
134
|
+
* allow nulls even in primary keys, so callers must check notNull, not just primary.
|
|
135
|
+
*
|
|
136
|
+
* Build object restrictions and RAW callbacks against the inner target alias. Static RAW SQL
|
|
137
|
+
* is passed through by Drizzle: references to the outer target can still force a target scan.
|
|
138
|
+
* A RAW callback must use its supplied table to benefit from the identity lookup.
|
|
139
|
+
*/
|
|
140
|
+
function targetIdentityInRelation(
|
|
141
|
+
client: RelationQueryBuilder,
|
|
142
|
+
relation: Relation,
|
|
143
|
+
parentTable: Table,
|
|
144
|
+
targetTable: Table,
|
|
145
|
+
throughTable: Table,
|
|
146
|
+
key: Column[],
|
|
147
|
+
): SQL {
|
|
148
|
+
const names = new Set([parentTable, targetTable, throughTable].map(getTableName));
|
|
149
|
+
let alias = '_pothos_related';
|
|
150
|
+
|
|
151
|
+
while (names.has(alias)) {
|
|
152
|
+
alias += '_';
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const matchedTable = aliasedTable(targetTable, alias);
|
|
156
|
+
const { filter, joinCondition } = relationToSQL(
|
|
157
|
+
relation,
|
|
158
|
+
parentTable,
|
|
159
|
+
matchedTable,
|
|
160
|
+
throughTable,
|
|
161
|
+
) as { filter: SQL; joinCondition: SQL };
|
|
162
|
+
const fields = Object.fromEntries(
|
|
163
|
+
key.map((column, i) => [String(i), sql`${aliasedTableColumn(column, alias)}`]),
|
|
164
|
+
);
|
|
165
|
+
const columns = key.map((column) => sql`${column}`);
|
|
166
|
+
const identity = columns.length === 1 ? columns[0] : sql`(${sql.join(columns, sql`, `)})`;
|
|
167
|
+
|
|
168
|
+
return inArray(
|
|
169
|
+
identity,
|
|
170
|
+
client.select(fields).from(throughTable).innerJoin(matchedTable, joinCondition).where(filter),
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// A fresh `count(*)` each time: `mapWith` mutates the `SQL` it is called on, so a shared one
|
|
175
|
+
// would be re-decoded by every query that selected it.
|
|
176
|
+
function countStar(): Record<string, SQL> {
|
|
177
|
+
return { count: count() };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// The count as a value the surrounding query can select. `count()` carries drizzle's `Number`
|
|
181
|
+
// decoder, but a `select` built around it decodes as the row it returns, so the mapping is
|
|
182
|
+
// restored here and the count comes back as a number on every dialect.
|
|
183
|
+
function countOf(rows: SQLWrapper): SQL<number> {
|
|
184
|
+
return sql`${rows.getSQL()}`.mapWith(Number);
|
|
185
|
+
}
|
package/src/utils/selections.ts
CHANGED
|
@@ -1,216 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { DBQueryConfig, TableRelationalConfig } from 'drizzle-orm';
|
|
3
|
-
import type { PothosDrizzleSchemaConfig } from './config.js';
|
|
4
|
-
import { deepEqual } from './deep-equal.js';
|
|
5
|
-
import type { LoaderMappings } from './loader-map.js';
|
|
6
|
-
|
|
7
|
-
export interface SelectionState {
|
|
8
|
-
table: TableRelationalConfig;
|
|
9
|
-
query: object;
|
|
10
|
-
allColumns: boolean;
|
|
11
|
-
columns: Set<string>;
|
|
12
|
-
with: Map<string, SelectionState>;
|
|
13
|
-
extras: Map<string, NonNullable<SelectionMap['extras']>[string]>;
|
|
14
|
-
mappings: LoaderMappings;
|
|
15
|
-
parent?: SelectionState;
|
|
16
|
-
depth: number;
|
|
17
|
-
skipDeferredFragments: boolean;
|
|
18
|
-
}
|
|
1
|
+
import type { DBQueryConfig } from 'drizzle-orm';
|
|
19
2
|
|
|
20
3
|
export type SelectionMap = DBQueryConfig<'one'>;
|
|
21
4
|
|
|
5
|
+
/** Drops keys holding `undefined`, so `{ where: cond ? filter : undefined }` reads as `{}`. */
|
|
22
6
|
export function omitUndefinedKeys<T extends object>(query: T): T {
|
|
23
7
|
const entries = Object.entries(query);
|
|
24
8
|
const defined = entries.filter(([, value]) => value !== undefined);
|
|
25
9
|
|
|
26
10
|
return defined.length === entries.length ? query : (Object.fromEntries(defined) as T);
|
|
27
11
|
}
|
|
28
|
-
|
|
29
|
-
export function selectionCompatible(
|
|
30
|
-
state: SelectionState,
|
|
31
|
-
selectionMap: SelectionMap | boolean,
|
|
32
|
-
ignoreQuery = false,
|
|
33
|
-
): boolean {
|
|
34
|
-
if (typeof selectionMap === 'boolean') {
|
|
35
|
-
return ignoreQuery || !selectionMap || Object.keys(state.query).length === 0;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const { with: withSelection, extras, columns: _, ...query } = selectionMap;
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
withSelection &&
|
|
42
|
-
Object.entries(withSelection).some(
|
|
43
|
-
([key, value]) =>
|
|
44
|
-
value &&
|
|
45
|
-
state.with.has(key) &&
|
|
46
|
-
// TODO: make sure nested extras are normalized
|
|
47
|
-
!selectionCompatible(state.with.get(key)!, value as SelectionMap),
|
|
48
|
-
)
|
|
49
|
-
) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (
|
|
54
|
-
extras &&
|
|
55
|
-
Object.entries(extras).some(([key, value]) => {
|
|
56
|
-
const existing = state.extras.get(key);
|
|
57
|
-
return existing && existing !== value;
|
|
58
|
-
})
|
|
59
|
-
) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return ignoreQuery || deepEqual(state.query, omitUndefinedKeys(query));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function stateCompatible(
|
|
67
|
-
state: SelectionState,
|
|
68
|
-
newState: SelectionState,
|
|
69
|
-
ignoreQuery = false,
|
|
70
|
-
): boolean {
|
|
71
|
-
for (const [name, relationState] of newState.with) {
|
|
72
|
-
if (state.with.has(name) && !stateCompatible(state.with.get(name)!, relationState)) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return ignoreQuery || deepEqual(state.query, newState.query);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function mergeState(state: SelectionState, newState: SelectionState) {
|
|
81
|
-
for (const [name, relationState] of newState.with) {
|
|
82
|
-
if (state.with.has(name)) {
|
|
83
|
-
mergeState(state.with.get(name)!, relationState);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (!state.allColumns) {
|
|
88
|
-
if (newState.allColumns) {
|
|
89
|
-
state.allColumns = true;
|
|
90
|
-
} else {
|
|
91
|
-
for (const name of newState.columns) {
|
|
92
|
-
state.columns.add(name);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
for (const [name, value] of newState.extras) {
|
|
98
|
-
state.extras.set(name, value);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function createState(
|
|
103
|
-
table: TableRelationalConfig,
|
|
104
|
-
skipDeferredFragments: boolean,
|
|
105
|
-
parent?: SelectionState,
|
|
106
|
-
): SelectionState {
|
|
107
|
-
return {
|
|
108
|
-
table,
|
|
109
|
-
skipDeferredFragments,
|
|
110
|
-
parent,
|
|
111
|
-
query: {},
|
|
112
|
-
columns: new Set(),
|
|
113
|
-
with: new Map(),
|
|
114
|
-
extras: new Map(),
|
|
115
|
-
mappings: {},
|
|
116
|
-
allColumns: false,
|
|
117
|
-
depth: parent ? parent.depth + 1 : 0,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function mergeSelection(
|
|
122
|
-
config: PothosDrizzleSchemaConfig,
|
|
123
|
-
state: SelectionState,
|
|
124
|
-
selection: SelectionMap | boolean,
|
|
125
|
-
) {
|
|
126
|
-
const {
|
|
127
|
-
with: withSelection,
|
|
128
|
-
extras,
|
|
129
|
-
columns,
|
|
130
|
-
...query
|
|
131
|
-
} = typeof selection === 'boolean' ? (selection === true ? {} : { columns: {} }) : selection;
|
|
132
|
-
if (withSelection) {
|
|
133
|
-
for (const [key, value] of Object.entries(withSelection)) {
|
|
134
|
-
const relation = state.table.relations[key];
|
|
135
|
-
|
|
136
|
-
if (!relation) {
|
|
137
|
-
throw new PothosValidationError(`Relation ${key} does not exist on ${state.table.name}`);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
merge(config.relations[relation.targetTableName], key, value as SelectionMap | boolean);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const normalizedQuery = omitUndefinedKeys(query);
|
|
145
|
-
if (Object.keys(normalizedQuery).length > 0) {
|
|
146
|
-
state.query = normalizedQuery;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (extras) {
|
|
150
|
-
for (const [key, value] of Object.entries(extras)) {
|
|
151
|
-
state.extras.set(key, value);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (state.allColumns) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (columns && !state.allColumns) {
|
|
160
|
-
for (const [key, value] of Object.entries(columns)) {
|
|
161
|
-
if (value) {
|
|
162
|
-
state.columns.add(key);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
} else {
|
|
166
|
-
state.allColumns = true;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function merge(table: TableRelationalConfig, key: string, value?: SelectionMap | boolean) {
|
|
170
|
-
if (!value) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (state.with.has(key)) {
|
|
175
|
-
mergeSelection(config, state.with.get(key)!, value);
|
|
176
|
-
} else {
|
|
177
|
-
const relatedState = createState(table, state.skipDeferredFragments, state);
|
|
178
|
-
mergeSelection(config, relatedState, value);
|
|
179
|
-
state.with.set(key, relatedState);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export function selectionToQuery(
|
|
185
|
-
config: PothosDrizzleSchemaConfig,
|
|
186
|
-
state: SelectionState,
|
|
187
|
-
): SelectionMap {
|
|
188
|
-
const query: SelectionMap & { extras: Record<string, unknown> } = {
|
|
189
|
-
...omitUndefinedKeys(state.query),
|
|
190
|
-
columns: undefined,
|
|
191
|
-
with: {},
|
|
192
|
-
extras: {},
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
if (!state.allColumns) {
|
|
196
|
-
query.columns = {};
|
|
197
|
-
for (const key of state.columns) {
|
|
198
|
-
query.columns![key] = true;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
for (const column of config.getPrimaryKey(state.table.name)) {
|
|
202
|
-
const tsName = config.columnToTsName(column);
|
|
203
|
-
query.columns![tsName] = true;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
for (const [key, value] of state.extras) {
|
|
208
|
-
query.extras![key] = value;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
state.with.forEach((sel, relation) => {
|
|
212
|
-
query.with![relation] = selectionToQuery(config, sel);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
return query;
|
|
216
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deep-equal.d.ts","sourceRoot":"","sources":["../../src/utils/deep-equal.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,WAwD5E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-graphql.d.ts","sourceRoot":"","sources":["../../src/utils/drizzle-graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { GraphQLResolveInfo } from 'graphql';
|
|
2
|
-
export type LoaderMappings = Record<string, {
|
|
3
|
-
field: string;
|
|
4
|
-
type: string;
|
|
5
|
-
mappings: LoaderMappings;
|
|
6
|
-
indirectPath: string[];
|
|
7
|
-
}>;
|
|
8
|
-
export declare function cacheKey(type: string, path: GraphQLResolveInfo['path'], subPath?: string[]): string;
|
|
9
|
-
export declare function setLoaderMappings(ctx: object, info: GraphQLResolveInfo, value: LoaderMappings): void;
|
|
10
|
-
export declare function getLoaderMapping(ctx: object, path: GraphQLResolveInfo['path'], type: string): LoaderMappings | null;
|
|
11
|
-
//# sourceMappingURL=loader-map.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"loader-map.d.ts","sourceRoot":"","sources":["../../src/utils/loader-map.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,MAAM,cAAc,GAAG,MAAM,CACjC,MAAM,EACN;IACE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CACF,CAAC;AAIF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAE,MAAM,EAAO,UAgB9F;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,cAAc,QAQ7F;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,yBAK3F"}
|
package/dts/utils/usage.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare const usageSymbol: unique symbol;
|
|
2
|
-
export declare function wrapWithUsageCheck<T extends object>(obj: T): T;
|
|
3
|
-
export declare function isUsed(obj: object): boolean;
|
|
4
|
-
export declare function extendWithUsage<T extends object, U extends object>(original: T, extension: U): T & U;
|
|
5
|
-
//# sourceMappingURL=usage.d.ts.map
|
package/dts/utils/usage.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/utils/usage.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,eAA8B,CAAC;AAEvD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CA4B9D;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE3C;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAChE,QAAQ,EAAE,CAAC,EACX,SAAS,EAAE,CAAC,GACX,CAAC,GAAG,CAAC,CAsBP"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deep-equal.d.ts","sourceRoot":"","sources":["../../src/utils/deep-equal.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,WAwD5E"}
|
package/esm/utils/deep-equal.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export function deepEqual(left, right, ignore) {
|
|
2
|
-
if (left === right) {
|
|
3
|
-
return true;
|
|
4
|
-
}
|
|
5
|
-
if (left && right && typeof left === 'object' && typeof right === 'object') {
|
|
6
|
-
var _left_valueOf, _right_valueOf;
|
|
7
|
-
if (Array.isArray(left)) {
|
|
8
|
-
if (!Array.isArray(right)) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
const { length } = left;
|
|
12
|
-
if (right.length !== length) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
for(let i = 0; i < length; i += 1){
|
|
16
|
-
if (!deepEqual(left[i], right[i])) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
const lValue = (_left_valueOf = left.valueOf) === null || _left_valueOf === void 0 ? void 0 : _left_valueOf.call(left);
|
|
23
|
-
const rValue = (_right_valueOf = right.valueOf) === null || _right_valueOf === void 0 ? void 0 : _right_valueOf.call(right);
|
|
24
|
-
if ((lValue != null || rValue != null) && typeof lValue !== 'object') {
|
|
25
|
-
return lValue === rValue;
|
|
26
|
-
}
|
|
27
|
-
const keys = Object.keys(left);
|
|
28
|
-
const keyLength = keys.length;
|
|
29
|
-
if (keyLength !== Object.keys(right).length) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
for (const key of keys){
|
|
33
|
-
if (ignore === null || ignore === void 0 ? void 0 : ignore.has(key)) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
if (!deepEqual(left[key], right[key])) {
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
//# sourceMappingURL=deep-equal.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/deep-equal.ts"],"names":["deepEqual","left","right","ignore","Array","isArray","length","i","lValue","valueOf","rValue","keys","Object","keyLength","key","has"],"mappings":"AAAA,OAAO,SAASA,UAAUC,IAAa,EAAEC,KAAc,EAAEC,MAAoB;IAC3E,IAAIF,SAASC,OAAO;QAClB,OAAO;IACT;IAEA,IAAID,QAAQC,SAAS,OAAOD,SAAS,YAAY,OAAOC,UAAU,UAAU;YAqB3DD,eACAC;QArBf,IAAIE,MAAMC,OAAO,CAACJ,OAAO;YACvB,IAAI,CAACG,MAAMC,OAAO,CAACH,QAAQ;gBACzB,OAAO;YACT;YAEA,MAAM,EAAEI,MAAM,EAAE,GAAGL;YAEnB,IAAIC,MAAMI,MAAM,KAAKA,QAAQ;gBAC3B,OAAO;YACT;YAEA,IAAK,IAAIC,IAAI,GAAGA,IAAID,QAAQC,KAAK,EAAG;gBAClC,IAAI,CAACP,UAAUC,IAAI,CAACM,EAAE,EAAEL,KAAK,CAACK,EAAE,GAAG;oBACjC,OAAO;gBACT;YACF;YAEA,OAAO;QACT;QAEA,MAAMC,UAASP,gBAAAA,KAAKQ,OAAO,cAAZR,oCAAAA,mBAAAA;QACf,MAAMS,UAASR,iBAAAA,MAAMO,OAAO,cAAbP,qCAAAA,oBAAAA;QAEf,IAAI,AAACM,CAAAA,UAAU,QAAQE,UAAU,IAAG,KAAM,OAAOF,WAAW,UAAU;YACpE,OAAOA,WAAWE;QACpB;QAEA,MAAMC,OAAOC,OAAOD,IAAI,CAACV;QACzB,MAAMY,YAAYF,KAAKL,MAAM;QAE7B,IAAIO,cAAcD,OAAOD,IAAI,CAACT,OAAOI,MAAM,EAAE;YAC3C,OAAO;QACT;QAEA,KAAK,MAAMQ,OAAOH,KAAM;YACtB,IAAIR,mBAAAA,6BAAAA,OAAQY,GAAG,CAACD,MAAM;gBACpB;YACF;YAEA,IACE,CAACd,UAAU,AAACC,IAAgC,CAACa,IAAI,EAAE,AAACZ,KAAiC,CAACY,IAAI,GAC1F;gBACA,OAAO;YACT;QACF;QAEA,OAAO;IACT;IAEA,OAAO;AACT"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"drizzle-graphql.d.ts","sourceRoot":"","sources":["../../src/utils/drizzle-graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC"}
|