@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.
Files changed (165) hide show
  1. package/CHANGELOG.md +345 -0
  2. package/README.md +784 -221
  3. package/dts/connection-helpers.d.ts +18 -8
  4. package/dts/connection-helpers.d.ts.map +1 -1
  5. package/dts/drizzle-field-builder.d.ts +4 -11
  6. package/dts/drizzle-field-builder.d.ts.map +1 -1
  7. package/dts/global-types.d.ts.map +1 -1
  8. package/dts/index.d.ts.map +1 -1
  9. package/dts/model-loader.d.ts +18 -17
  10. package/dts/model-loader.d.ts.map +1 -1
  11. package/dts/types.d.ts +80 -20
  12. package/dts/types.d.ts.map +1 -1
  13. package/dts/utils/adapter.d.ts +39 -0
  14. package/dts/utils/adapter.d.ts.map +1 -0
  15. package/dts/utils/await-selections.d.ts +12 -0
  16. package/dts/utils/await-selections.d.ts.map +1 -0
  17. package/dts/utils/config.d.ts +23 -3
  18. package/dts/utils/config.d.ts.map +1 -1
  19. package/dts/utils/cursors.d.ts +6 -6
  20. package/dts/utils/cursors.d.ts.map +1 -1
  21. package/dts/utils/map-query.d.ts +22 -21
  22. package/dts/utils/map-query.d.ts.map +1 -1
  23. package/dts/utils/path-info.d.ts +13 -0
  24. package/dts/utils/path-info.d.ts.map +1 -0
  25. package/dts/utils/relation-filter.d.ts +48 -0
  26. package/dts/utils/relation-filter.d.ts.map +1 -0
  27. package/dts/utils/selections.d.ts +2 -21
  28. package/dts/utils/selections.d.ts.map +1 -1
  29. package/esm/connection-helpers.d.ts +18 -8
  30. package/esm/connection-helpers.d.ts.map +1 -1
  31. package/esm/connection-helpers.js +52 -19
  32. package/esm/connection-helpers.js.map +1 -1
  33. package/esm/drizzle-field-builder.d.ts +4 -11
  34. package/esm/drizzle-field-builder.d.ts.map +1 -1
  35. package/esm/drizzle-field-builder.js +138 -96
  36. package/esm/drizzle-field-builder.js.map +1 -1
  37. package/esm/field-builder.js +61 -47
  38. package/esm/field-builder.js.map +1 -1
  39. package/esm/global-types.d.ts.map +1 -1
  40. package/esm/index.d.ts.map +1 -1
  41. package/esm/index.js +37 -61
  42. package/esm/index.js.map +1 -1
  43. package/esm/model-loader.d.ts +18 -17
  44. package/esm/model-loader.d.ts.map +1 -1
  45. package/esm/model-loader.js +76 -45
  46. package/esm/model-loader.js.map +1 -1
  47. package/esm/schema-builder.js +40 -149
  48. package/esm/schema-builder.js.map +1 -1
  49. package/esm/types.d.ts +80 -20
  50. package/esm/types.d.ts.map +1 -1
  51. package/esm/types.js.map +1 -1
  52. package/esm/utils/adapter.d.ts +39 -0
  53. package/esm/utils/adapter.d.ts.map +1 -0
  54. package/esm/utils/adapter.js +137 -0
  55. package/esm/utils/adapter.js.map +1 -0
  56. package/esm/utils/await-selections.d.ts +12 -0
  57. package/esm/utils/await-selections.d.ts.map +1 -0
  58. package/esm/utils/await-selections.js +19 -0
  59. package/esm/utils/await-selections.js.map +1 -0
  60. package/esm/utils/config.d.ts +23 -3
  61. package/esm/utils/config.d.ts.map +1 -1
  62. package/esm/utils/config.js +1 -4
  63. package/esm/utils/config.js.map +1 -1
  64. package/esm/utils/cursors.d.ts +6 -6
  65. package/esm/utils/cursors.d.ts.map +1 -1
  66. package/esm/utils/cursors.js +55 -90
  67. package/esm/utils/cursors.js.map +1 -1
  68. package/esm/utils/map-query.d.ts +22 -21
  69. package/esm/utils/map-query.d.ts.map +1 -1
  70. package/esm/utils/map-query.js +40 -354
  71. package/esm/utils/map-query.js.map +1 -1
  72. package/esm/utils/path-info.d.ts +13 -0
  73. package/esm/utils/path-info.d.ts.map +1 -0
  74. package/esm/utils/path-info.js +37 -0
  75. package/esm/utils/path-info.js.map +1 -0
  76. package/esm/utils/relation-filter.d.ts +48 -0
  77. package/esm/utils/relation-filter.d.ts.map +1 -0
  78. package/esm/utils/relation-filter.js +92 -0
  79. package/esm/utils/relation-filter.js.map +1 -0
  80. package/esm/utils/selections.d.ts +2 -21
  81. package/esm/utils/selections.d.ts.map +1 -1
  82. package/esm/utils/selections.js +1 -133
  83. package/esm/utils/selections.js.map +1 -1
  84. package/lib/connection-helpers.js +51 -18
  85. package/lib/connection-helpers.js.map +1 -1
  86. package/lib/drizzle-field-builder.js +136 -94
  87. package/lib/drizzle-field-builder.js.map +1 -1
  88. package/lib/field-builder.js +58 -44
  89. package/lib/field-builder.js.map +1 -1
  90. package/lib/index.js +36 -60
  91. package/lib/index.js.map +1 -1
  92. package/lib/model-loader.js +76 -45
  93. package/lib/model-loader.js.map +1 -1
  94. package/lib/schema-builder.js +40 -149
  95. package/lib/schema-builder.js.map +1 -1
  96. package/lib/types.js.map +1 -1
  97. package/lib/utils/adapter.js +147 -0
  98. package/lib/utils/adapter.js.map +1 -0
  99. package/lib/utils/await-selections.js +20 -0
  100. package/lib/utils/await-selections.js.map +1 -0
  101. package/lib/utils/config.js +1 -4
  102. package/lib/utils/config.js.map +1 -1
  103. package/lib/utils/cursors.js +47 -88
  104. package/lib/utils/cursors.js.map +1 -1
  105. package/lib/utils/map-query.js +28 -359
  106. package/lib/utils/map-query.js.map +1 -1
  107. package/lib/utils/path-info.js +39 -0
  108. package/lib/utils/path-info.js.map +1 -0
  109. package/lib/utils/relation-filter.js +91 -0
  110. package/lib/utils/relation-filter.js.map +1 -0
  111. package/lib/utils/selections.js +3 -158
  112. package/lib/utils/selections.js.map +1 -1
  113. package/package.json +8 -6
  114. package/src/connection-helpers.ts +167 -53
  115. package/src/drizzle-field-builder.ts +296 -176
  116. package/src/field-builder.ts +110 -77
  117. package/src/global-types.ts +0 -32
  118. package/src/index.ts +42 -68
  119. package/src/model-loader.ts +110 -71
  120. package/src/schema-builder.ts +76 -169
  121. package/src/types.ts +175 -44
  122. package/src/utils/adapter.ts +197 -0
  123. package/src/utils/await-selections.ts +31 -0
  124. package/src/utils/config.ts +1 -5
  125. package/src/utils/cursors.ts +53 -81
  126. package/src/utils/map-query.ts +51 -734
  127. package/src/utils/path-info.ts +40 -0
  128. package/src/utils/relation-filter.ts +185 -0
  129. package/src/utils/selections.ts +2 -207
  130. package/dts/utils/deep-equal.d.ts +0 -2
  131. package/dts/utils/deep-equal.d.ts.map +0 -1
  132. package/dts/utils/drizzle-graphql.d.ts +0 -2
  133. package/dts/utils/drizzle-graphql.d.ts.map +0 -1
  134. package/dts/utils/loader-map.d.ts +0 -11
  135. package/dts/utils/loader-map.d.ts.map +0 -1
  136. package/dts/utils/usage.d.ts +0 -5
  137. package/dts/utils/usage.d.ts.map +0 -1
  138. package/esm/utils/deep-equal.d.ts +0 -2
  139. package/esm/utils/deep-equal.d.ts.map +0 -1
  140. package/esm/utils/deep-equal.js +0 -45
  141. package/esm/utils/deep-equal.js.map +0 -1
  142. package/esm/utils/drizzle-graphql.d.ts +0 -2
  143. package/esm/utils/drizzle-graphql.d.ts.map +0 -1
  144. package/esm/utils/drizzle-graphql.js +0 -232
  145. package/esm/utils/drizzle-graphql.js.map +0 -1
  146. package/esm/utils/loader-map.d.ts +0 -11
  147. package/esm/utils/loader-map.d.ts.map +0 -1
  148. package/esm/utils/loader-map.js +0 -35
  149. package/esm/utils/loader-map.js.map +0 -1
  150. package/esm/utils/usage.d.ts +0 -5
  151. package/esm/utils/usage.d.ts.map +0 -1
  152. package/esm/utils/usage.js +0 -59
  153. package/esm/utils/usage.js.map +0 -1
  154. package/lib/utils/deep-equal.js +0 -55
  155. package/lib/utils/deep-equal.js.map +0 -1
  156. package/lib/utils/drizzle-graphql.js +0 -236
  157. package/lib/utils/drizzle-graphql.js.map +0 -1
  158. package/lib/utils/loader-map.js +0 -56
  159. package/lib/utils/loader-map.js.map +0 -1
  160. package/lib/utils/usage.js +0 -83
  161. package/lib/utils/usage.js.map +0 -1
  162. package/src/utils/deep-equal.ts +0 -57
  163. package/src/utils/drizzle-graphql.ts +0 -274
  164. package/src/utils/loader-map.ts +0 -49
  165. package/src/utils/usage.ts +0 -62
@@ -2,171 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get createState () {
13
- return createState;
14
- },
15
- get mergeSelection () {
16
- return mergeSelection;
17
- },
18
- get mergeState () {
19
- return mergeState;
20
- },
21
- get omitUndefinedKeys () {
5
+ Object.defineProperty(exports, "omitUndefinedKeys", {
6
+ enumerable: true,
7
+ get: function() {
22
8
  return omitUndefinedKeys;
23
- },
24
- get selectionCompatible () {
25
- return selectionCompatible;
26
- },
27
- get selectionToQuery () {
28
- return selectionToQuery;
29
- },
30
- get stateCompatible () {
31
- return stateCompatible;
32
9
  }
33
10
  });
34
- const _core = require("@pothos/core");
35
- const _deepequal = require("./deep-equal.js");
36
11
  function omitUndefinedKeys(query) {
37
12
  const entries = Object.entries(query);
38
13
  const defined = entries.filter(([, value])=>value !== undefined);
39
14
  return defined.length === entries.length ? query : Object.fromEntries(defined);
40
15
  }
41
- function selectionCompatible(state, selectionMap, ignoreQuery = false) {
42
- if (typeof selectionMap === 'boolean') {
43
- return ignoreQuery || !selectionMap || Object.keys(state.query).length === 0;
44
- }
45
- const { with: withSelection, extras, columns: _, ...query } = selectionMap;
46
- if (withSelection && Object.entries(withSelection).some(([key, value])=>value && state.with.has(key) && // TODO: make sure nested extras are normalized
47
- !selectionCompatible(state.with.get(key), value))) {
48
- return false;
49
- }
50
- if (extras && Object.entries(extras).some(([key, value])=>{
51
- const existing = state.extras.get(key);
52
- return existing && existing !== value;
53
- })) {
54
- return false;
55
- }
56
- return ignoreQuery || (0, _deepequal.deepEqual)(state.query, omitUndefinedKeys(query));
57
- }
58
- function stateCompatible(state, newState, ignoreQuery = false) {
59
- for (const [name, relationState] of newState.with){
60
- if (state.with.has(name) && !stateCompatible(state.with.get(name), relationState)) {
61
- return false;
62
- }
63
- }
64
- return ignoreQuery || (0, _deepequal.deepEqual)(state.query, newState.query);
65
- }
66
- function mergeState(state, newState) {
67
- for (const [name, relationState] of newState.with){
68
- if (state.with.has(name)) {
69
- mergeState(state.with.get(name), relationState);
70
- }
71
- }
72
- if (!state.allColumns) {
73
- if (newState.allColumns) {
74
- state.allColumns = true;
75
- } else {
76
- for (const name of newState.columns){
77
- state.columns.add(name);
78
- }
79
- }
80
- }
81
- for (const [name, value] of newState.extras){
82
- state.extras.set(name, value);
83
- }
84
- }
85
- function createState(table, skipDeferredFragments, parent) {
86
- return {
87
- table,
88
- skipDeferredFragments,
89
- parent,
90
- query: {},
91
- columns: new Set(),
92
- with: new Map(),
93
- extras: new Map(),
94
- mappings: {},
95
- allColumns: false,
96
- depth: parent ? parent.depth + 1 : 0
97
- };
98
- }
99
- function mergeSelection(config, state, selection) {
100
- const { with: withSelection, extras, columns, ...query } = typeof selection === 'boolean' ? selection === true ? {} : {
101
- columns: {}
102
- } : selection;
103
- if (withSelection) {
104
- for (const [key, value] of Object.entries(withSelection)){
105
- const relation = state.table.relations[key];
106
- if (!relation) {
107
- throw new _core.PothosValidationError(`Relation ${key} does not exist on ${state.table.name}`);
108
- }
109
- merge(config.relations[relation.targetTableName], key, value);
110
- }
111
- }
112
- const normalizedQuery = omitUndefinedKeys(query);
113
- if (Object.keys(normalizedQuery).length > 0) {
114
- state.query = normalizedQuery;
115
- }
116
- if (extras) {
117
- for (const [key, value] of Object.entries(extras)){
118
- state.extras.set(key, value);
119
- }
120
- }
121
- if (state.allColumns) {
122
- return;
123
- }
124
- if (columns && !state.allColumns) {
125
- for (const [key, value] of Object.entries(columns)){
126
- if (value) {
127
- state.columns.add(key);
128
- }
129
- }
130
- } else {
131
- state.allColumns = true;
132
- }
133
- function merge(table, key, value) {
134
- if (!value) {
135
- return;
136
- }
137
- if (state.with.has(key)) {
138
- mergeSelection(config, state.with.get(key), value);
139
- } else {
140
- const relatedState = createState(table, state.skipDeferredFragments, state);
141
- mergeSelection(config, relatedState, value);
142
- state.with.set(key, relatedState);
143
- }
144
- }
145
- }
146
- function selectionToQuery(config, state) {
147
- const query = {
148
- ...omitUndefinedKeys(state.query),
149
- columns: undefined,
150
- with: {},
151
- extras: {}
152
- };
153
- if (!state.allColumns) {
154
- query.columns = {};
155
- for (const key of state.columns){
156
- query.columns[key] = true;
157
- }
158
- for (const column of config.getPrimaryKey(state.table.name)){
159
- const tsName = config.columnToTsName(column);
160
- query.columns[tsName] = true;
161
- }
162
- }
163
- for (const [key, value] of state.extras){
164
- query.extras[key] = value;
165
- }
166
- state.with.forEach((sel, relation)=>{
167
- query.with[relation] = selectionToQuery(config, sel);
168
- });
169
- return query;
170
- }
171
16
 
172
17
  //# sourceMappingURL=selections.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/selections.ts"],"names":["createState","mergeSelection","mergeState","omitUndefinedKeys","selectionCompatible","selectionToQuery","stateCompatible","query","entries","Object","defined","filter","value","undefined","length","fromEntries","state","selectionMap","ignoreQuery","keys","with","withSelection","extras","columns","_","some","key","has","get","existing","deepEqual","newState","name","relationState","allColumns","add","set","table","skipDeferredFragments","parent","Set","Map","mappings","depth","config","selection","relation","relations","PothosValidationError","merge","targetTableName","normalizedQuery","relatedState","column","getPrimaryKey","tsName","columnToTsName","forEach","sel"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/utils/selections.ts"],"names":["omitUndefinedKeys","query","entries","Object","defined","filter","value","undefined","length","fromEntries"],"mappings":";;;;+BAKgBA;;;eAAAA;;;AAAT,SAASA,kBAAoCC,KAAQ;IAC1D,MAAMC,UAAUC,OAAOD,OAAO,CAACD;IAC/B,MAAMG,UAAUF,QAAQG,MAAM,CAAC,CAAC,GAAGC,MAAM,GAAKA,UAAUC;IAExD,OAAOH,QAAQI,MAAM,KAAKN,QAAQM,MAAM,GAAGP,QAASE,OAAOM,WAAW,CAACL;AACzE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pothos/plugin-drizzle",
3
- "version": "0.18.1",
3
+ "version": "0.19.0",
4
4
  "description": "A Pothos plugin for drizzle",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./dts/index.d.ts",
@@ -33,23 +33,25 @@
33
33
  "access": "public",
34
34
  "provenance": true
35
35
  },
36
+ "dependencies": {
37
+ "@pothos/selection-mapper": "0.1.0"
38
+ },
36
39
  "peerDependencies": {
37
40
  "@pothos/core": "*",
38
- "drizzle-orm": ">=1.0.0-beta.2",
41
+ "drizzle-orm": ">=1.0.0-rc.2",
39
42
  "graphql": "^16.10.0 || ^17.0.0"
40
43
  },
41
44
  "devDependencies": {
42
45
  "@libsql/client": "^0.17.2",
43
- "drizzle-graphql": "^0.8.5",
44
46
  "drizzle-kit": "1.0.0-rc.2",
45
47
  "drizzle-orm": "1.0.0-rc.2",
46
48
  "graphql-scalars": "^1.25.0",
47
49
  "graphql-tag": "^2.12.6",
48
50
  "postgres": "^3.4.9",
49
- "@pothos/core": "4.13.1",
50
- "@pothos/plugin-errors": "4.9.1",
51
- "@pothos/plugin-relay": "4.7.1",
51
+ "@pothos/core": "4.14.0",
52
52
  "@pothos/plugin-add-graphql": "4.3.1",
53
+ "@pothos/plugin-errors": "4.9.1",
54
+ "@pothos/plugin-relay": "4.7.2",
53
55
  "@pothos/plugin-scope-auth": "4.1.7",
54
56
  "@pothos/plugin-with-input": "4.1.5",
55
57
  "@pothos/test-utils": "2.2.1"
@@ -1,13 +1,25 @@
1
- import type { InputFieldMap, InputShapeFromFields, SchemaTypes } from '@pothos/core';
1
+ import {
2
+ completeValue,
3
+ type InputFieldMap,
4
+ type InputShapeFromFields,
5
+ isThenable,
6
+ type MaybeAsyncSelection,
7
+ type MaybePromise,
8
+ type SchemaTypes,
9
+ } from '@pothos/core';
10
+ import type { PathSegment } from '@pothos/selection-mapper';
2
11
  import type {
3
12
  BuildQueryResult,
4
13
  DBQueryConfig,
5
14
  RelationsFilter,
15
+ SQL,
6
16
  TableRelationalConfig,
7
17
  } from 'drizzle-orm';
8
18
  import type { GraphQLResolveInfo } from 'graphql';
9
19
  import type { DrizzleRef } from './interface-ref.js';
10
20
  import type { QueryForDrizzleConnection } from './types.js';
21
+ import { drizzleAdapter } from './utils/adapter.js';
22
+ import { checkAwaitSelections } from './utils/await-selections.js';
11
23
  import { getSchemaConfig } from './utils/config.js';
12
24
  import {
13
25
  type DrizzleCursorConnectionQueryOptions,
@@ -17,12 +29,7 @@ import {
17
29
  } from './utils/cursors.js';
18
30
  import { queryFromInfo } from './utils/map-query.js';
19
31
  import { getRefFromModel } from './utils/refs.js';
20
- import {
21
- createState,
22
- mergeSelection,
23
- omitUndefinedKeys,
24
- selectionToQuery,
25
- } from './utils/selections.js';
32
+ import { omitUndefinedKeys, type SelectionMap } from './utils/selections.js';
26
33
 
27
34
  export function drizzleConnectionHelpers<
28
35
  Types extends SchemaTypes,
@@ -60,14 +67,18 @@ export function drizzleConnectionHelpers<
60
67
  }: {
61
68
  args?: (t: PothosSchemaTypes.InputFieldBuilder<Types, 'Arg'>) => ExtraArgs;
62
69
  select?: (
70
+ // The node's selection: its table is the connection field's, which the helper does not know.
63
71
  nestedSelection: <T extends true | {}>(selection?: T) => T,
64
72
  args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
65
73
  ctx: Types['Context'],
66
- ) => Selection;
74
+ ) => MaybeAsyncSelection<Types, Selection>;
67
75
  query?: QueryForDrizzleConnection<Types, TableConfig> extends infer QueryConfig
68
76
  ?
69
77
  | QueryConfig
70
- | ((args: InputShapeFromFields<ExtraArgs>, context: Types['Context']) => QueryConfig)
78
+ | ((
79
+ args: InputShapeFromFields<ExtraArgs>,
80
+ context: Types['Context'],
81
+ ) => MaybeAsyncSelection<Types, QueryConfig>)
71
82
  : never;
72
83
  defaultSize?:
73
84
  | number
@@ -79,23 +90,47 @@ export function drizzleConnectionHelpers<
79
90
  | number
80
91
  | ((args: PothosSchemaTypes.DefaultConnectionArguments, ctx: Types['Context']) => number);
81
92
  resolveNode?: (edge: EdgeShape) => NodeShape;
82
- },
93
+ } = {},
83
94
  ) {
84
95
  const config = getSchemaConfig(builder);
96
+ const adapter = drizzleAdapter(config);
85
97
  const tableName =
86
98
  typeof refOrType === 'string'
87
99
  ? refOrType
88
100
  : (refOrType as DrizzleRef<Types, Type extends DrizzleRef<Types, infer T> ? T : Type>)
89
101
  .tableName;
90
102
 
91
- function resolve<Parent = undefined>(
103
+ interface BaseQuery {
104
+ limit?: number;
105
+ orderBy?: unknown;
106
+ where?: SQL;
107
+ columns?: Record<string, boolean>;
108
+ extras?: DrizzleCursorConnectionQueryOptions['extras'];
109
+ }
110
+
111
+ /** The user's `query`, a promise when its callback is async, which the caller awaits. */
112
+ const baseQueryFor = (
113
+ args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
114
+ ctx: Types['Context'],
115
+ ): MaybePromise<BaseQuery> =>
116
+ completeValue(
117
+ (typeof query === 'function' ? query(args, ctx) : query) as MaybePromise<
118
+ BaseQuery | null | undefined
119
+ >,
120
+ orEmpty,
121
+ );
122
+
123
+ // Built once per helper, so a synchronous `resolve` allocates nothing beyond the connection.
124
+ const resolveList = (
125
+ baseQuery: BaseQuery,
92
126
  list: (EdgeShape & {})[],
93
127
  args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
94
128
  ctx: Types['Context'],
95
- parent?: Parent,
96
- ) {
97
- const { select, cursorFields } = getQueryArgs(args, ctx);
129
+ parent: unknown,
130
+ ) => {
131
+ const { select, cursorFields } = getQueryArgs(args, ctx, baseQuery);
98
132
  const formatCursor = getCursorFormatter(cursorFields, config);
133
+
99
134
  return wrapConnectionResult(
100
135
  list,
101
136
  args,
@@ -103,24 +138,42 @@ export function drizzleConnectionHelpers<
103
138
  formatCursor,
104
139
  (resolveNode as never) ?? ((edge: unknown) => edge),
105
140
  parent,
106
- ) as unknown as {
107
- parent: Parent;
108
- edges: (Omit<EdgeShape, 'cursor' | 'node'> & { node: NodeShape; cursor: string })[];
109
- pageInfo: {
110
- startCursor: string | null;
111
- endCursor: string | null;
112
- hasPreviousPage: boolean;
113
- hasNextPage: boolean;
114
- };
115
- };
141
+ );
142
+ };
143
+
144
+ function resolve<Parent = undefined>(
145
+ list: (EdgeShape & {})[],
146
+ args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
147
+ ctx: Types['Context'],
148
+ parent?: Parent,
149
+ ) {
150
+ const baseQuery = baseQueryFor(args, ctx);
151
+
152
+ return (
153
+ isThenable(baseQuery)
154
+ ? baseQuery.then((resolved) => resolveList(resolved, list, args, ctx, parent))
155
+ : resolveList(baseQuery, list, args, ctx, parent)
156
+ ) as MaybeAsyncSelection<
157
+ Types,
158
+ {
159
+ parent: Parent;
160
+ edges: (Omit<EdgeShape, 'cursor' | 'node'> & { node: NodeShape; cursor: string })[];
161
+ pageInfo: {
162
+ startCursor: string | null;
163
+ endCursor: string | null;
164
+ hasPreviousPage: boolean;
165
+ hasNextPage: boolean;
166
+ };
167
+ }
168
+ >;
116
169
  }
117
170
 
118
171
  const getQueryArgs = (
119
172
  args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
120
173
  ctx: {},
174
+ baseQuery: BaseQuery,
121
175
  ) => {
122
- const { limit, orderBy, where, ...fieldQuery } =
123
- (typeof query === 'function' ? query(args, ctx) : query) ?? {};
176
+ const { limit, orderBy, where, ...fieldQuery } = baseQuery;
124
177
  const table = config.relations[tableName];
125
178
 
126
179
  const { cursorFields, columns, ...connectionQuery } = drizzleCursorConnectionQuery({
@@ -151,13 +204,45 @@ export function drizzleConnectionHelpers<
151
204
  };
152
205
  };
153
206
 
154
- type NestedSelection = <T extends true | {}>(selection?: T, path?: string[]) => T;
207
+ // The `nestedSelection` of the field's `select`, whatever table its type names.
208
+ type NestedSelection = (selection?: SelectionMap | true, path?: PathSegment[]) => unknown;
209
+
210
+ /** The drizzle query `getQuery` builds: the node selection, with the connection's own arguments. */
211
+ type ConnectionQuery = Omit<Selection, 'orderBy'> & {
212
+ orderBy: {
213
+ [K in TableConfig['table']['_'] extends { columns: infer Columns } ? keyof Columns : never]?:
214
+ | 'asc'
215
+ | 'desc'
216
+ | undefined;
217
+ };
218
+ where: RelationsFilter<TableConfig, Types['DrizzleRelations']>;
219
+ };
220
+
221
+ /**
222
+ * What `getQuery` returns for a given `awaitSelections`. `[Await] extends [false]` rather than
223
+ * `Await extends true`, so a caller passing a `boolean` variable — which infers `Await` as
224
+ * `boolean`, neither literal — is handed the promise to deal with, rather than a synchronous
225
+ * type it cannot rely on.
226
+ */
227
+ type ConnectionQueryReturn<Await extends boolean> = [Await] extends [false]
228
+ ? ConnectionQuery
229
+ : MaybePromise<ConnectionQuery>;
155
230
 
156
- function getQuery(
231
+ /**
232
+ * The connection's query, built from the helper's own `select` and `query` and the selection
233
+ * beneath the field. Synchronous unless `awaitSelections` says otherwise: an async `select` or
234
+ * `query`, or an async selection beneath the connection, throws rather than returning a promise
235
+ * the declared type denies.
236
+ */
237
+ function getQuery<Await extends boolean = false>(
157
238
  args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
158
239
  ctx: Types['Context'],
159
240
  nestedSelectionOrInfo: NestedSelection | GraphQLResolveInfo,
160
- ) {
241
+ options?: {
242
+ /** Whether the caller will await the query. */
243
+ awaitSelections?: Await;
244
+ },
245
+ ): ConnectionQueryReturn<Await> {
161
246
  const nestedSelection: NestedSelection =
162
247
  typeof nestedSelectionOrInfo === 'function'
163
248
  ? nestedSelectionOrInfo
@@ -166,43 +251,72 @@ export function drizzleConnectionHelpers<
166
251
  info: nestedSelectionOrInfo,
167
252
  context: ctx,
168
253
  config,
169
- select,
254
+ select: select as SelectionMap,
170
255
  path,
171
256
  });
172
- const nestedSelect: Record<string, unknown> | true = select
173
- ? select((sel) => nestedSelection(sel, ['edges', 'node']), args, ctx)
174
- : nestedSelection(true, ['edges', 'node']);
175
- const queryArgs = getQueryArgs(args, ctx);
176
-
177
- const selectState = createState(
178
- config.relations[tableName],
179
- builder.options.drizzle?.skipDeferredFragments ?? true,
180
- );
257
+ // Both callbacks start now; the query waits for whichever of them is async.
258
+ const nestedSelect: MaybePromise<Record<string, unknown> | true> = select
259
+ ? select((sel) => nestedSelection(sel as SelectionMap, ['edges', 'node']) as never, args, ctx)
260
+ : (nestedSelection(true, ['edges', 'node']) as never);
261
+ let baseQuery: MaybePromise<object>;
181
262
 
182
- mergeSelection(config, selectState, queryArgs.select);
263
+ try {
264
+ baseQuery = baseQueryFor(args, ctx);
265
+ } catch (error) {
266
+ // The selection has already started. Preserve the query error while handling any
267
+ // later rejection from the selection that this invocation can no longer consume.
268
+ if (isThenable(nestedSelect)) {
269
+ nestedSelect.then(
270
+ () => {},
271
+ () => {},
272
+ );
273
+ }
183
274
 
184
- if (typeof nestedSelect === 'object' && nestedSelect) {
185
- mergeSelection(config, selectState, nestedSelect);
275
+ throw error;
186
276
  }
187
277
 
188
- const baseQuery = typeof query === 'function' ? query(args, ctx) : (query ?? {});
189
- const queryResult = selectionToQuery(config, selectState);
278
+ const built: MaybePromise<object> =
279
+ isThenable(nestedSelect) || isThenable(baseQuery)
280
+ ? Promise.all([nestedSelect, baseQuery]).then(([nested, base]) =>
281
+ buildQuery(nested, base, args, ctx),
282
+ )
283
+ : buildQuery(nestedSelect, baseQuery, args, ctx);
284
+
285
+ return checkAwaitSelections(
286
+ built,
287
+ options?.awaitSelections,
288
+ 'getQuery',
289
+ `the ${String(tableName)} connection`,
290
+ ) as ConnectionQueryReturn<Await>;
291
+ }
292
+
293
+ // Built once per helper, so a synchronous `getQuery` allocates nothing beyond the query.
294
+ function buildQuery(
295
+ nestedSelect: Record<string, unknown> | true,
296
+ baseQuery: BaseQuery,
297
+ args: InputShapeFromFields<ExtraArgs> & PothosSchemaTypes.DefaultConnectionArguments,
298
+ ctx: Types['Context'],
299
+ ) {
300
+ const node = adapter.createNode(config.relations[tableName]);
301
+
302
+ adapter.mergeQuery(node, getQueryArgs(args, ctx, baseQuery).select as SelectionMap);
303
+
304
+ if (typeof nestedSelect === 'object' && nestedSelect) {
305
+ adapter.mergeQuery(node, nestedSelect);
306
+ }
190
307
 
191
308
  return omitUndefinedKeys({
192
309
  ...baseQuery,
193
- ...queryResult,
194
- }) as unknown as Omit<Selection, 'orderBy'> & {
195
- orderBy: {
196
- [K in TableConfig['table']['_'] extends { columns: infer Columns }
197
- ? keyof Columns
198
- : never]?: 'asc' | 'desc' | undefined;
199
- };
200
- where: RelationsFilter<TableConfig, Types['DrizzleRelations']>;
201
- };
310
+ ...adapter.toQuery(node),
311
+ });
202
312
  }
203
313
 
204
314
  const getArgs = () => (createArgs ? builder.args(createArgs) : {}) as ExtraArgs;
205
315
 
316
+ function orEmpty(baseQuery: BaseQuery | null | undefined): BaseQuery {
317
+ return baseQuery ?? ({} as BaseQuery);
318
+ }
319
+
206
320
  return {
207
321
  ref: (typeof refOrType === 'string'
208
322
  ? getRefFromModel(refOrType, builder)