/// import { loadSchema, normalizePath } from '@zenstackhq/testtools'; import fs from 'fs'; import path from 'path'; import tmp from 'tmp'; describe('Tanstack Query Plugin Tests', () => { let origDir: string; beforeAll(() => { origDir = process.cwd(); }); afterEach(() => { process.chdir(origDir); }); const sharedModel = ` model User { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt email String @unique role role @default(USER) posts post_Item[] } enum role { USER ADMIN } model post_Item { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String author User? @relation(fields: [authorId], references: [id], onDelete: Cascade) authorId String? published Boolean @default(false) viewCount Int @default(0) } model Foo { id String @id @@ignore } `; const reactAppSource = { name: 'main.ts', content: ` import { useFindFirstpost_Item, useInfiniteFindManypost_Item, useCreatepost_Item } from './hooks'; function query() { const { data, queryKey } = useFindFirstpost_Item({include: { author: true }}, { enabled: true, optimisticUpdate: false }); console.log(queryKey); console.log(data?.viewCount); console.log(data?.author?.email); } function infiniteQuery() { const { data, queryKey, fetchNextPage, hasNextPage } = useInfiniteFindManypost_Item(); useInfiniteFindManypost_Item({ where: { published: true } }); useInfiniteFindManypost_Item(undefined, { enabled: true, getNextPageParam: () => null }); console.log(queryKey); console.log(data?.pages[0]?.[0]?.published); console.log(data?.pageParams[0]); } async function mutation() { const { mutateAsync } = useCreatepost_Item(); const data = await mutateAsync({ data: { title: 'hello' }, include: { author: true } }); console.log(data?.viewCount); console.log(data?.author?.email); } `, }; it('react-query run plugin v4', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'react' version = 'v4' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['react@18.2.0', '@types/react@18.2.0', '@tanstack/react-query@4.29.7'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [reactAppSource], } ); }); it('react-query run plugin v5', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'react' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['react@18.2.0', '@types/react@18.2.0', '@tanstack/react-query@5.56.x'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [ reactAppSource, { name: 'suspense.ts', content: ` import { useSuspenseInfiniteFindManypost_Item } from './hooks'; function suspenseInfiniteQuery() { const { data, queryKey, fetchNextPage, hasNextPage } = useSuspenseInfiniteFindManypost_Item(); useSuspenseInfiniteFindManypost_Item({ where: { published: true } }); useSuspenseInfiniteFindManypost_Item(undefined, { getNextPageParam: () => null }); console.log(queryKey); console.log(data?.pages[0]?.[0]?.published); console.log(data?.pageParams[0]); } `, }, ], } ); }); const vueAppSource = { name: 'main.ts', content: ` import { useFindFirstpost_Item, useInfiniteFindManypost_Item, useCreatepost_Item } from './hooks'; function query() { const { data, queryKey } = useFindFirstpost_Item({include: { author: true }}, { enabled: true, optimisticUpdate: false }); console.log(queryKey); console.log(data.value?.viewCount); console.log(data.value?.author?.email); } function infiniteQuery() { const { data, queryKey, fetchNextPage, hasNextPage } = useInfiniteFindManypost_Item(); useInfiniteFindManypost_Item({ where: { published: true } }, { enabled: true, getNextPageParam: () => null }); useInfiniteFindManypost_Item(undefined, { getNextPageParam: () => null }); console.log(queryKey); console.log(data.value?.pages[0]?.[0]?.published); console.log(data.value?.pageParams[0]); } async function mutation() { const { mutateAsync } = useCreatepost_Item(); const data = await mutateAsync({ data: { title: 'hello' }, include: { author: true } }); console.log(data?.viewCount); console.log(data?.author?.email); } `, }; it('vue-query run plugin v4', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'vue' version = 'v4' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['vue@^3.3.4', '@tanstack/vue-query@4.37.0'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [vueAppSource], } ); }); it('vue-query run plugin v5', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'vue' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['vue@^3.3.4', '@tanstack/vue-query@latest'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [vueAppSource], } ); }); const svelteAppSource = { name: 'main.ts', content: ` import { get } from 'svelte/store'; import { useFindFirstpost_Item, useInfiniteFindManypost_Item, useCreatepost_Item } from './hooks'; function query() { const { data, queryKey } = get(useFindFirstpost_Item({include: { author: true }}, { enabled: true, optimisticUpdate: false })); console.log(queryKey); console.log(data?.viewCount); console.log(data?.author?.email); } function infiniteQuery() { const { data, queryKey, fetchNextPage, hasNextPage } = get(useInfiniteFindManypost_Item()); useInfiniteFindManypost_Item({ where: { published: true } }); useInfiniteFindManypost_Item(undefined, { enabled: true, getNextPageParam: () => null }); console.log(queryKey); console.log(data?.pages[0]?.[0]?.published); console.log(data?.pageParams[0]); } async function mutation() { const { mutateAsync } = get(useCreatepost_Item()); const data = await mutateAsync({ data: { title: 'hello' }, include: { author: true } }); console.log(data?.viewCount); console.log(data?.author?.email); } `, }; it('svelte-query run plugin v4', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'svelte' version = 'v4' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['svelte@^3.0.0', '@tanstack/svelte-query@4.29.7'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [svelteAppSource], } ); }); it('svelte-query run plugin v5', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'svelte' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: ['svelte@^3.0.0', '@tanstack/svelte-query@^5.0.0'], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [svelteAppSource], } ); }); const angularAppSource = { name: 'main.ts', content: ` import { Component, inject } from '@angular/core'; import { useFindFirstpost_Item, useInfiniteFindManypost_Item, useCreatepost_Item } from './hooks'; @Component({ selector: 'app-test', template: '
Test Component
' }) export class TestComponent { query() { const { data } = useFindFirstpost_Item({include: { author: true }}, { enabled: true, optimisticUpdate: false }); console.log(data()?.viewCount); console.log(data()?.author?.email); } infiniteQuery() { const { data, fetchNextPage, hasNextPage } = useInfiniteFindManypost_Item(); useInfiniteFindManypost_Item({ where: { published: true } }); useInfiniteFindManypost_Item(undefined, { enabled: true, getNextPageParam: () => null }); console.log(data()?.pages[0][0].published); console.log(data()?.pageParams[0]); } async mutation() { const { mutateAsync } = useCreatepost_Item(); const data = await mutateAsync({ data: { title: 'hello' }, include: { author: true } }); console.log(data?.viewCount); console.log(data?.author?.email); } } `, }; it('angular-query run plugin v5', async () => { await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/hooks' target = 'angular' } ${sharedModel} `, { provider: 'postgresql', pushDb: false, extraDependencies: [ '@angular/core@^20.0.0', '@angular/common@^20.0.0', '@angular/platform-browser@^20.0.0', '@tanstack/angular-query-experimental@5.84.x', 'rxjs@^7.8.0', 'zone.js@^0.15.0', ], copyDependencies: [path.resolve(__dirname, '../dist')], compile: true, extraSourceFiles: [angularAppSource], } ); }); it('clear output', async () => { const { name: projectDir } = tmp.dirSync(); fs.mkdirSync(path.join(projectDir, 'tanstack'), { recursive: true }); fs.writeFileSync(path.join(projectDir, 'tanstack', 'test.txt'), 'hello'); await loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/tanstack' target = 'react' } model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt email String @unique password String @omit } `, { pushDb: false, projectDir, extraDependencies: [`${normalizePath(path.join(__dirname, '../dist'))}`], } ); expect(fs.existsSync(path.join(projectDir, 'tanstack', 'test.txt'))).toBeFalsy(); }); it('existing output as file', async () => { const { name: projectDir } = tmp.dirSync(); fs.writeFileSync(path.join(projectDir, 'tanstack'), 'hello'); await expect( loadSchema( ` plugin tanstack { provider = '${normalizePath(path.resolve(__dirname, '../dist'))}' output = '$projectRoot/tanstack' target = 'react' } model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt email String password String @omit } `, { pushDb: false, projectDir, extraDependencies: [`${normalizePath(path.join(__dirname, '../dist'))}`] } ) ).rejects.toThrow('already exists and is not a directory'); }); });