@@ -21,6 +21,7 @@ import { name } from '.';
21
21
22
22
const supportedTargets = [ 'react' , 'vue' , 'svelte' ] ;
23
23
type TargetFramework = ( typeof supportedTargets ) [ number ] ;
24
+ type TanStackVersion = 'v4' | 'v5' ;
24
25
25
26
export async function generate ( model : Model , options : PluginOptions , dmmf : DMMF . Document ) {
26
27
let outDir = requireOption < string > ( options , 'output' ) ;
@@ -38,15 +39,20 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
38
39
) ;
39
40
}
40
41
41
- generateIndex ( project , outDir , models , target ) ;
42
+ const version = typeof options . version === 'string' ? options . version : 'v4' ;
43
+ if ( version !== 'v4' && version !== 'v5' ) {
44
+ throw new PluginError ( options . name , `Unsupported version "${ version } ": use "v4" or "v5"` ) ;
45
+ }
46
+
47
+ generateIndex ( project , outDir , models , target , version ) ;
42
48
43
49
models . forEach ( ( dataModel ) => {
44
50
const mapping = dmmf . mappings . modelOperations . find ( ( op ) => op . model === dataModel . name ) ;
45
51
if ( ! mapping ) {
46
52
warnings . push ( `Unable to find mapping for model ${ dataModel . name } ` ) ;
47
53
return ;
48
54
}
49
- generateModelHooks ( target , project , outDir , dataModel , mapping ) ;
55
+ generateModelHooks ( target , version , project , outDir , dataModel , mapping ) ;
50
56
} ) ;
51
57
52
58
await saveProject ( project ) ;
@@ -55,6 +61,7 @@ export async function generate(model: Model, options: PluginOptions, dmmf: DMMF.
55
61
56
62
function generateQueryHook (
57
63
target : TargetFramework ,
64
+ version : TanStackVersion ,
58
65
sf : SourceFile ,
59
66
model : string ,
60
67
operation : string ,
@@ -71,7 +78,7 @@ function generateQueryHook(
71
78
const inputType = `Prisma.SelectSubset<T, ${ argsType } >` ;
72
79
const returnType =
73
80
overrideReturnType ?? ( returnArray ? `Array<Prisma.${ model } GetPayload<T>>` : `Prisma.${ model } GetPayload<T>` ) ;
74
- const optionsType = makeQueryOptions ( target , returnType , infinite ) ;
81
+ const optionsType = makeQueryOptions ( target , returnType , infinite , version ) ;
75
82
76
83
const func = sf . addFunction ( {
77
84
name : `use${ infinite ? 'Infinite' : '' } ${ capOperation } ${ model } ` ,
@@ -89,9 +96,14 @@ function generateQueryHook(
89
96
isExported : true ,
90
97
} ) ;
91
98
99
+ if ( version === 'v5' && infinite && [ 'react' , 'svelte' ] . includes ( target ) ) {
100
+ // initialPageParam and getNextPageParam options are required in v5
101
+ func . addStatements ( [ `options = options ?? { initialPageParam: undefined, getNextPageParam: () => null };` ] ) ;
102
+ }
103
+
92
104
func . addStatements ( [
93
105
makeGetContext ( target ) ,
94
- `return ${ infinite ? 'infiniteQuery' : 'query' } < ${ returnType } > ('${ model } ', \`\${endpoint}/${ lowerCaseFirst (
106
+ `return ${ infinite ? 'infiniteQuery' : 'query' } ('${ model } ', \`\${endpoint}/${ lowerCaseFirst (
95
107
model
96
108
) } /${ operation } \`, args, options, fetch);`,
97
109
] ) ;
@@ -217,6 +229,7 @@ function generateMutationHook(
217
229
218
230
function generateModelHooks (
219
231
target : TargetFramework ,
232
+ version : TanStackVersion ,
220
233
project : Project ,
221
234
outDir : string ,
222
235
model : DataModel ,
@@ -235,7 +248,7 @@ function generateModelHooks(
235
248
isTypeOnly : true ,
236
249
moduleSpecifier : prismaImport ,
237
250
} ) ;
238
- sf . addStatements ( makeBaseImports ( target ) ) ;
251
+ sf . addStatements ( makeBaseImports ( target , version ) ) ;
239
252
240
253
// create is somehow named "createOne" in the DMMF
241
254
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -251,19 +264,31 @@ function generateModelHooks(
251
264
// findMany
252
265
if ( mapping . findMany ) {
253
266
// regular findMany
254
- generateQueryHook ( target , sf , model . name , 'findMany' , true , true ) ;
267
+ generateQueryHook ( target , version , sf , model . name , 'findMany' , true , true ) ;
255
268
// infinite findMany
256
- generateQueryHook ( target , sf , model . name , 'findMany' , true , true , undefined , undefined , undefined , true ) ;
269
+ generateQueryHook (
270
+ target ,
271
+ version ,
272
+ sf ,
273
+ model . name ,
274
+ 'findMany' ,
275
+ true ,
276
+ true ,
277
+ undefined ,
278
+ undefined ,
279
+ undefined ,
280
+ true
281
+ ) ;
257
282
}
258
283
259
284
// findUnique
260
285
if ( mapping . findUnique ) {
261
- generateQueryHook ( target , sf , model . name , 'findUnique' , false , false ) ;
286
+ generateQueryHook ( target , version , sf , model . name , 'findUnique' , false , false ) ;
262
287
}
263
288
264
289
// findFirst
265
290
if ( mapping . findFirst ) {
266
- generateQueryHook ( target , sf , model . name , 'findFirst' , false , true ) ;
291
+ generateQueryHook ( target , version , sf , model . name , 'findFirst' , false , true ) ;
267
292
}
268
293
269
294
// update
@@ -301,6 +326,7 @@ function generateModelHooks(
301
326
if ( mapping . aggregate ) {
302
327
generateQueryHook (
303
328
target ,
329
+ version ,
304
330
sf ,
305
331
modelNameCap ,
306
332
'aggregate' ,
@@ -385,6 +411,7 @@ function generateModelHooks(
385
411
386
412
generateQueryHook (
387
413
target ,
414
+ version ,
388
415
sf ,
389
416
model . name ,
390
417
'groupBy' ,
@@ -400,6 +427,7 @@ function generateModelHooks(
400
427
{
401
428
generateQueryHook (
402
429
target ,
430
+ version ,
403
431
sf ,
404
432
model . name ,
405
433
'count' ,
@@ -410,22 +438,25 @@ function generateModelHooks(
410
438
}
411
439
}
412
440
413
- function generateIndex ( project : Project , outDir : string , models : DataModel [ ] , target : string ) {
441
+ function generateIndex (
442
+ project : Project ,
443
+ outDir : string ,
444
+ models : DataModel [ ] ,
445
+ target : string ,
446
+ version : TanStackVersion
447
+ ) {
414
448
const sf = project . createSourceFile ( path . join ( outDir , 'index.ts' ) , undefined , { overwrite : true } ) ;
415
449
sf . addStatements ( models . map ( ( d ) => `export * from './${ paramCase ( d . name ) } ';` ) ) ;
450
+ const runtimeImportBase = makeRuntimeImportBase ( version ) ;
416
451
switch ( target ) {
417
452
case 'react' :
418
- sf . addStatements ( `export { Provider } from '@zenstackhq/tanstack-query/runtime /react';` ) ;
453
+ sf . addStatements ( `export { Provider } from '${ runtimeImportBase } /react';` ) ;
419
454
break ;
420
455
case 'vue' :
421
- sf . addStatements (
422
- `export { VueQueryContextKey, provideHooksContext } from '@zenstackhq/tanstack-query/runtime/vue';`
423
- ) ;
456
+ sf . addStatements ( `export { VueQueryContextKey, provideHooksContext } from '${ runtimeImportBase } /vue';` ) ;
424
457
break ;
425
458
case 'svelte' :
426
- sf . addStatements (
427
- `export { SvelteQueryContextKey, setHooksContext } from '@zenstackhq/tanstack-query/runtime/svelte';`
428
- ) ;
459
+ sf . addStatements ( `export { SvelteQueryContextKey, setHooksContext } from '${ runtimeImportBase } /svelte';` ) ;
429
460
break ;
430
461
}
431
462
}
@@ -443,45 +474,60 @@ function makeGetContext(target: TargetFramework) {
443
474
}
444
475
}
445
476
446
- function makeBaseImports ( target : TargetFramework ) {
477
+ function makeBaseImports ( target : TargetFramework , version : TanStackVersion ) {
478
+ const runtimeImportBase = makeRuntimeImportBase ( version ) ;
447
479
const shared = [
448
- `import { query, infiniteQuery, postMutation, putMutation, deleteMutation } from '@zenstackhq/tanstack-query/runtime /${ target } ';` ,
449
- `import type { PickEnumerable, CheckSelect } from '@zenstackhq/tanstack-query/runtime ';` ,
480
+ `import { query, infiniteQuery, postMutation, putMutation, deleteMutation } from '${ runtimeImportBase } /${ target } ';` ,
481
+ `import type { PickEnumerable, CheckSelect } from '${ runtimeImportBase } ';` ,
450
482
] ;
451
483
switch ( target ) {
452
484
case 'react' :
453
485
return [
454
486
`import { useContext } from 'react';` ,
455
- `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions } from '@tanstack/react-query';` ,
456
- `import { RequestHandlerContext } from '@zenstackhq/tanstack-query/runtime /${ target } ';` ,
487
+ `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions, InfiniteData } from '@tanstack/react-query';` ,
488
+ `import { RequestHandlerContext } from '${ runtimeImportBase } /${ target } ';` ,
457
489
...shared ,
458
490
] ;
459
491
case 'vue' :
460
492
return [
461
- `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions } from '@tanstack/vue-query';` ,
462
- `import { getContext } from '@zenstackhq/tanstack-query/runtime /${ target } ';` ,
493
+ `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions, InfiniteData } from '@tanstack/vue-query';` ,
494
+ `import { getContext } from '${ runtimeImportBase } /${ target } ';` ,
463
495
...shared ,
464
496
] ;
465
497
case 'svelte' :
466
498
return [
467
499
`import { getContext } from 'svelte';` ,
468
500
`import { derived } from 'svelte/store';` ,
469
501
`import type { MutationOptions, QueryOptions, CreateInfiniteQueryOptions } from '@tanstack/svelte-query';` ,
470
- `import { SvelteQueryContextKey, type RequestHandlerContext } from '@zenstackhq/tanstack-query/runtime/${ target } ';` ,
502
+ ...( version === 'v5'
503
+ ? [ `import type { InfiniteData, StoreOrVal } from '@tanstack/svelte-query';` ]
504
+ : [ ] ) ,
505
+ `import { SvelteQueryContextKey, type RequestHandlerContext } from '${ runtimeImportBase } /${ target } ';` ,
471
506
...shared ,
472
507
] ;
473
508
default :
474
509
throw new PluginError ( name , `Unsupported target: ${ target } ` ) ;
475
510
}
476
511
}
477
512
478
- function makeQueryOptions ( target : string , returnType : string , infinite : boolean ) {
513
+ function makeQueryOptions ( target : string , returnType : string , infinite : boolean , version : TanStackVersion ) {
479
514
switch ( target ) {
480
515
case 'react' :
516
+ return infinite
517
+ ? version === 'v4'
518
+ ? `Omit<UseInfiniteQueryOptions<${ returnType } >, 'queryKey'>`
519
+ : `Omit<UseInfiniteQueryOptions<${ returnType } , unknown, InfiniteData<${ returnType } >>, 'queryKey'>`
520
+ : `Omit<UseQueryOptions<${ returnType } >, 'queryKey'>` ;
481
521
case 'vue' :
482
- return `Use${ infinite ? 'Infinite' : '' } QueryOptions<${ returnType } >` ;
522
+ return `Omit< Use${ infinite ? 'Infinite' : '' } QueryOptions<${ returnType } >, 'queryKey' >` ;
483
523
case 'svelte' :
484
- return `${ infinite ? 'CreateInfinite' : '' } QueryOptions<${ returnType } >` ;
524
+ return infinite
525
+ ? version === 'v4'
526
+ ? `Omit<CreateInfiniteQueryOptions<${ returnType } >, 'queryKey'>`
527
+ : `StoreOrVal<Omit<CreateInfiniteQueryOptions<${ returnType } , unknown, InfiniteData<${ returnType } >>, 'queryKey'>>`
528
+ : version === 'v4'
529
+ ? `Omit<QueryOptions<${ returnType } >, 'queryKey'>`
530
+ : `StoreOrVal<Omit<QueryOptions<${ returnType } >, 'queryKey'>>` ;
485
531
default :
486
532
throw new PluginError ( name , `Unsupported target: ${ target } ` ) ;
487
533
}
@@ -499,3 +545,7 @@ function makeMutationOptions(target: string, returnType: string, argsType: strin
499
545
throw new PluginError ( name , `Unsupported target: ${ target } ` ) ;
500
546
}
501
547
}
548
+
549
+ function makeRuntimeImportBase ( version : TanStackVersion ) {
550
+ return `@zenstackhq/tanstack-query/runtime${ version === 'v5' ? '-v5' : '' } ` ;
551
+ }
0 commit comments