@@ -180,47 +180,82 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
180
180
return ;
181
181
}
182
182
183
- for ( const kind of [ 'select' , 'include' ] as const ) {
184
- if ( args [ kind ] && typeof args [ kind ] === 'object' ) {
185
- for ( const [ field , value ] of Object . entries < any > ( args [ kind ] ) ) {
186
- const fieldInfo = resolveField ( this . options . modelMeta , model , field ) ;
187
- if ( ! fieldInfo ) {
188
- continue ;
189
- }
183
+ const selectors = [
184
+ ( payload : any ) => ( { data : payload . select , kind : 'select' as const , isCount : false } ) ,
185
+ ( payload : any ) => ( { data : payload . include , kind : 'include' as const , isCount : false } ) ,
186
+ ( payload : any ) => ( {
187
+ data : payload . select ?. _count ?. select ,
188
+ kind : 'select' as const ,
189
+ isCount : true ,
190
+ } ) ,
191
+ ( payload : any ) => ( {
192
+ data : payload . include ?. _count ?. select ,
193
+ kind : 'include' as const ,
194
+ isCount : true ,
195
+ } ) ,
196
+ ] ;
197
+
198
+ for ( const selector of selectors ) {
199
+ const { data, kind, isCount } = selector ( args ) ;
200
+ if ( ! data || typeof data !== 'object' ) {
201
+ continue ;
202
+ }
190
203
191
- if ( this . isDelegateOrDescendantOfDelegate ( fieldInfo ?. type ) && value ) {
192
- // delegate model, recursively inject hierarchy
193
- if ( args [ kind ] [ field ] ) {
194
- if ( args [ kind ] [ field ] === true ) {
195
- // make sure the payload is an object
196
- args [ kind ] [ field ] = { } ;
197
- }
198
- await this . injectSelectIncludeHierarchy ( fieldInfo . type , args [ kind ] [ field ] ) ;
204
+ for ( const [ field , value ] of Object . entries < any > ( data ) ) {
205
+ const fieldInfo = resolveField ( this . options . modelMeta , model , field ) ;
206
+ if ( ! fieldInfo ) {
207
+ continue ;
208
+ }
209
+
210
+ if ( this . isDelegateOrDescendantOfDelegate ( fieldInfo ?. type ) && value ) {
211
+ // delegate model, recursively inject hierarchy
212
+ if ( data [ field ] ) {
213
+ if ( data [ field ] === true ) {
214
+ // make sure the payload is an object
215
+ data [ field ] = { } ;
199
216
}
217
+ await this . injectSelectIncludeHierarchy ( fieldInfo . type , data [ field ] ) ;
200
218
}
219
+ }
201
220
202
- // refetch the field select/include value because it may have been
203
- // updated during injection
204
- const fieldValue = args [ kind ] [ field ] ;
221
+ // refetch the field select/include value because it may have been
222
+ // updated during injection
223
+ const fieldValue = data [ field ] ;
205
224
206
- if ( fieldValue !== undefined ) {
207
- if ( fieldValue . orderBy ) {
208
- // `orderBy` may contain fields from base types
209
- enumerate ( fieldValue . orderBy ) . forEach ( ( item ) =>
210
- this . injectWhereHierarchy ( fieldInfo . type , item )
211
- ) ;
212
- }
225
+ if ( fieldValue !== undefined ) {
226
+ if ( fieldValue . orderBy ) {
227
+ // `orderBy` may contain fields from base types
228
+ enumerate ( fieldValue . orderBy ) . forEach ( ( item ) =>
229
+ this . injectWhereHierarchy ( fieldInfo . type , item )
230
+ ) ;
231
+ }
213
232
214
- if ( this . injectBaseFieldSelect ( model , field , fieldValue , args , kind ) ) {
215
- delete args [ kind ] [ field ] ;
216
- } else if ( fieldInfo . isDataModel ) {
217
- let nextValue = fieldValue ;
218
- if ( nextValue === true ) {
219
- // make sure the payload is an object
220
- args [ kind ] [ field ] = nextValue = { } ;
233
+ let injected = false ;
234
+ if ( ! isCount ) {
235
+ injected = await this . injectBaseFieldSelect ( model , field , fieldValue , args , kind ) ;
236
+ if ( injected ) {
237
+ delete data [ field ] ;
238
+ }
239
+ } else {
240
+ const injectTarget = { [ kind ] : { } } ;
241
+ injected = await this . injectBaseFieldSelect ( model , field , fieldValue , injectTarget , kind , true ) ;
242
+ if ( injected ) {
243
+ delete data [ field ] ;
244
+ if ( Object . keys ( data ) . length === 0 ) {
245
+ delete args [ kind ] [ '_count' ] ;
221
246
}
222
- await this . injectSelectIncludeHierarchy ( fieldInfo . type , nextValue ) ;
247
+ const merged = deepmerge ( args [ kind ] , injectTarget [ kind ] ) ;
248
+ args [ kind ] = merged ;
249
+ }
250
+ }
251
+
252
+ if ( ! injected && fieldInfo . isDataModel ) {
253
+ let nextValue = fieldValue ;
254
+ if ( nextValue === true ) {
255
+ // make sure the payload is an object
256
+ data [ field ] = nextValue = { } ;
223
257
}
258
+ await this . injectSelectIncludeHierarchy ( fieldInfo . type , nextValue ) ;
224
259
}
225
260
}
226
261
}
@@ -272,7 +307,8 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
272
307
field : string ,
273
308
value : any ,
274
309
selectInclude : any ,
275
- context : 'select' | 'include'
310
+ context : 'select' | 'include' ,
311
+ forCount = false
276
312
) {
277
313
const fieldInfo = resolveField ( this . options . modelMeta , model , field ) ;
278
314
if ( ! fieldInfo ?. inheritedFrom ) {
@@ -286,24 +322,33 @@ export class DelegateProxyHandler extends DefaultPrismaProxyHandler {
286
322
const baseRelationName = this . makeAuxRelationName ( base ) ;
287
323
288
324
// prepare base layer select/include
289
- // let selectOrInclude = 'select';
290
325
let thisLayer : any ;
291
326
if ( target . include ) {
292
- // selectOrInclude = 'include';
293
327
thisLayer = target . include ;
294
328
} else if ( target . select ) {
295
- // selectOrInclude = 'select';
296
329
thisLayer = target . select ;
297
330
} else {
298
- // selectInclude = 'include';
299
331
thisLayer = target . select = { } ;
300
332
}
301
333
302
334
if ( base . name === fieldInfo . inheritedFrom ) {
303
335
if ( ! thisLayer [ baseRelationName ] ) {
304
336
thisLayer [ baseRelationName ] = { [ context ] : { } } ;
305
337
}
306
- thisLayer [ baseRelationName ] [ context ] [ field ] = value ;
338
+ if ( forCount ) {
339
+ if (
340
+ ! thisLayer [ baseRelationName ] [ context ] [ '_count' ] ||
341
+ typeof thisLayer [ baseRelationName ] [ context ] !== 'object'
342
+ ) {
343
+ thisLayer [ baseRelationName ] [ context ] [ '_count' ] = { } ;
344
+ }
345
+ thisLayer [ baseRelationName ] [ context ] [ '_count' ] = deepmerge (
346
+ thisLayer [ baseRelationName ] [ context ] [ '_count' ] ,
347
+ { select : { [ field ] : value } }
348
+ ) ;
349
+ } else {
350
+ thisLayer [ baseRelationName ] [ context ] [ field ] = value ;
351
+ }
307
352
break ;
308
353
} else {
309
354
if ( ! thisLayer [ baseRelationName ] ) {
0 commit comments