@undp/create-app 0.2.2 β 0.2.4
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/README.md +8 -9
- package/bin/generateFiles/generateGitIgnore.js +73 -0
- package/bin/generateFiles/generateLayoutForNext.js +10 -5
- package/bin/generateFiles/generatePackageJson.js +3 -7
- package/bin/generateFiles/generatePageForNext.js +102 -0
- package/bin/generateFiles/index.js +2 -0
- package/bin/index.js +15 -7
- package/bin/promptUser.js +17 -4
- package/bin/templates/next/auth/app/layout.tsx +2 -1
- package/bin/templates/next/basic/app/layout.tsx +2 -1
- package/bin/templates/queryIntegrationForNext/integration/tanstack-query.tsx +27 -0
- package/bin/templates/vite/query/src/integration/tanstack-query.tsx +2 -1
- package/bin/templates/vite/query+router/src/integration/tanstack-query.tsx +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ποΈ UNDP Create App CLI 
|
|
2
2
|
|
|
3
|
-
**`@undp/create-app`** is UNDPβs official **project scaffolding tool** for quickly bootstrapping frontend applications using **React**, and **TypeScript** β complete with sensible defaults for ESLint, Prettier
|
|
3
|
+
**`@undp/create-app`** is UNDPβs official **project scaffolding tool** for quickly bootstrapping frontend applications using **React**, and **TypeScript** β complete with sensible defaults for ESLint, Prettier.
|
|
4
4
|
|
|
5
5
|
[NPM Package](https://www.npmjs.com/package/@undp/create-app)
|
|
6
6
|
|
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
## π Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
- π **Vite support** for fast SPA development, including optional **routing**
|
|
11
|
+
- βοΈ **React + TypeScript** setup out of the box
|
|
12
|
+
- ποΈ Includes **Tailwind CSS** for styling
|
|
13
|
+
- ποΈ Includes **Zustand** for state management
|
|
14
|
+
- π **Vite support** for fast SPA development, including optional **routing** with **Tanstack router**
|
|
15
15
|
- π **Next.js support** for full-stack apps, including optional **authentication** with **Better Auth**
|
|
16
|
-
-
|
|
16
|
+
- π¨ Preconfigured for **UNDPβs Design System**
|
|
17
|
+
- β‘οΈ Optional integration with **Tanstack query** for data fetching
|
|
17
18
|
- π Optional integration with **@undp/data-viz** for interactive data visualization
|
|
18
|
-
-
|
|
19
|
+
- β¨ **ESLint** + **Prettier** preconfigured for consistent code style
|
|
19
20
|
|
|
20
21
|
---
|
|
21
22
|
|
|
@@ -26,9 +27,7 @@ All setups include **Tailwind CSS** for styling and **Zustand** for state manage
|
|
|
26
27
|
| Framework | Variants | Description |
|
|
27
28
|
|------------|-----------|-------------|
|
|
28
29
|
| **Vite** | Basic | Minimal React + TypeScript setup |
|
|
29
|
-
| **Vite** | + Query | Adds TanStack Query for data fetching |
|
|
30
30
|
| **Vite** | + Router | Adds TanStack Router for routing |
|
|
31
|
-
| **Vite** | + Router + Query | Full-featured Vite setup |
|
|
32
31
|
| **Next.js** | Basic | SSR and file-based routing |
|
|
33
32
|
| **Next.js** | + Auth | Includes authentication via Better Auth |
|
|
34
33
|
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export function generateGitIgnore(isVite) {
|
|
2
|
+
if (isVite) return `# Logs
|
|
3
|
+
logs
|
|
4
|
+
*.log
|
|
5
|
+
npm-debug.log*
|
|
6
|
+
yarn-debug.log*
|
|
7
|
+
yarn-error.log*
|
|
8
|
+
pnpm-debug.log*
|
|
9
|
+
lerna-debug.log*
|
|
10
|
+
|
|
11
|
+
node_modules
|
|
12
|
+
build
|
|
13
|
+
dist
|
|
14
|
+
dist-ssr
|
|
15
|
+
*.local
|
|
16
|
+
.eslintcache
|
|
17
|
+
stats.html
|
|
18
|
+
|
|
19
|
+
# Editor directories and files
|
|
20
|
+
.vscode/*
|
|
21
|
+
!.vscode/extensions.json
|
|
22
|
+
.idea
|
|
23
|
+
.DS_Store
|
|
24
|
+
*.suo
|
|
25
|
+
*.ntvs*
|
|
26
|
+
*.njsproj
|
|
27
|
+
*.sln
|
|
28
|
+
*.sw?
|
|
29
|
+
`
|
|
30
|
+
return `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
31
|
+
|
|
32
|
+
# dependencies
|
|
33
|
+
/node_modules
|
|
34
|
+
/.pnp
|
|
35
|
+
.pnp.*
|
|
36
|
+
.yarn/*
|
|
37
|
+
!.yarn/patches
|
|
38
|
+
!.yarn/plugins
|
|
39
|
+
!.yarn/releases
|
|
40
|
+
!.yarn/versions
|
|
41
|
+
|
|
42
|
+
# testing
|
|
43
|
+
/coverage
|
|
44
|
+
|
|
45
|
+
# next.js
|
|
46
|
+
/.next/
|
|
47
|
+
/out/
|
|
48
|
+
|
|
49
|
+
# production
|
|
50
|
+
/build
|
|
51
|
+
|
|
52
|
+
# misc
|
|
53
|
+
.DS_Store
|
|
54
|
+
*.pem
|
|
55
|
+
|
|
56
|
+
# debug
|
|
57
|
+
npm-debug.log*
|
|
58
|
+
yarn-debug.log*
|
|
59
|
+
yarn-error.log*
|
|
60
|
+
.pnpm-debug.log*
|
|
61
|
+
|
|
62
|
+
# env files (can opt-in for committing if needed)
|
|
63
|
+
.env*
|
|
64
|
+
|
|
65
|
+
# vercel
|
|
66
|
+
.vercel
|
|
67
|
+
|
|
68
|
+
# typescript
|
|
69
|
+
*.tsbuildinfo
|
|
70
|
+
next-env.d.ts
|
|
71
|
+
`
|
|
72
|
+
}
|
|
73
|
+
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
export function generateLayoutForNext(dataViz, projectName) {
|
|
1
|
+
export function generateLayoutForNext(dataViz, projectName, query) {
|
|
2
2
|
return `import type { Metadata } from 'next';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
3
4
|
|
|
4
5
|
import HeaderEl from '@/components/Header';
|
|
5
|
-
import FooterEl from '@/components/Footer'
|
|
6
|
+
import FooterEl from '@/components/Footer';${query ? `
|
|
7
|
+
import TanStackQueryProvider from '@/integration/tanstack-query';`:''}
|
|
6
8
|
|
|
7
9
|
import './globals.css';
|
|
8
10
|
import '@undp/design-system-react/style.css';${dataViz ? `
|
|
@@ -16,14 +18,17 @@ export const metadata: Metadata = {
|
|
|
16
18
|
export default function RootLayout({
|
|
17
19
|
children,
|
|
18
20
|
}: Readonly<{
|
|
19
|
-
children:
|
|
21
|
+
children: ReactNode;
|
|
20
22
|
}>) {
|
|
21
23
|
return (
|
|
22
24
|
<html lang='en'>
|
|
23
25
|
<body className='flex flex-col gap-0 min-h-screen'>
|
|
24
26
|
<HeaderEl />
|
|
25
|
-
<main className='grow-1 flex flex-col justify-center'
|
|
26
|
-
<
|
|
27
|
+
<main className='grow-1 flex flex-col justify-center'>${query ? `
|
|
28
|
+
<TanStackQueryProvider>
|
|
29
|
+
<div className='flex flex-col justify-center'>{children}</div>
|
|
30
|
+
</TanStackQueryProvider>` : `
|
|
31
|
+
<div className='flex flex-col justify-center'>{children}</div>`}
|
|
27
32
|
</main>
|
|
28
33
|
<FooterEl />
|
|
29
34
|
</body>
|
|
@@ -38,16 +38,9 @@ export function generatePackageJson(config) {
|
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
switch (config.framework) {
|
|
41
|
-
case 'vite-query':
|
|
42
|
-
dependencies['@tanstack/react-query'] = '^5.90.7';
|
|
43
|
-
break;
|
|
44
41
|
case 'vite-router':
|
|
45
42
|
dependencies['@tanstack/react-router'] = '^1.135.0';
|
|
46
43
|
break;
|
|
47
|
-
case 'vite-full':
|
|
48
|
-
dependencies['@tanstack/react-query'] = '^5.90.7';
|
|
49
|
-
dependencies['@tanstack/react-router'] = '^1.135.0';
|
|
50
|
-
break;
|
|
51
44
|
case 'next-basic':
|
|
52
45
|
dependencies['next'] = '16.0.1';
|
|
53
46
|
break;
|
|
@@ -58,6 +51,9 @@ export function generatePackageJson(config) {
|
|
|
58
51
|
default:
|
|
59
52
|
break;
|
|
60
53
|
}
|
|
54
|
+
if (config.query) {
|
|
55
|
+
dependencies['@tanstack/react-query'] = '^5.90.7';
|
|
56
|
+
}
|
|
61
57
|
if (config.libraries.includes('@undp/data-viz')) {
|
|
62
58
|
const dataVizVer = `^${getLatestVersion('@undp/data-viz')}`
|
|
63
59
|
dependencies['@undp/data-viz'] = dataVizVer;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
export function generatePageForNext(query) {
|
|
2
|
+
return `'use client';
|
|
3
|
+
|
|
4
|
+
import { P } from '@undp/design-system-react/Typography';
|
|
5
|
+
import { Button } from '@undp/design-system-react/Button';
|
|
6
|
+
import Image from 'next/image';${query ? `
|
|
7
|
+
import { useQuery } from '@tanstack/react-query';
|
|
8
|
+
import { Spinner } from '@undp/design-system-react/Spinner';` :''}
|
|
9
|
+
|
|
10
|
+
import { useCounterActions, useCounter } from '@/stores/counter';${query ? `
|
|
11
|
+
|
|
12
|
+
function useTodoData() {
|
|
13
|
+
return useQuery({
|
|
14
|
+
queryKey: ['todos'],
|
|
15
|
+
queryFn: () =>
|
|
16
|
+
Promise.resolve([
|
|
17
|
+
{ id: 1, name: 'Alice' },
|
|
18
|
+
{ id: 2, name: 'Bob' },
|
|
19
|
+
{ id: 3, name: 'Charlie' },
|
|
20
|
+
]),
|
|
21
|
+
});
|
|
22
|
+
}` :''}
|
|
23
|
+
|
|
24
|
+
export default function Home() {
|
|
25
|
+
const count = useCounter();
|
|
26
|
+
const { increment, decrement } = useCounterActions();${query ? `
|
|
27
|
+
|
|
28
|
+
const { data, isLoading, isError } = useTodoData();
|
|
29
|
+
|
|
30
|
+
if (isLoading) return <Spinner size='lg' className='my-20 m-auto' />;
|
|
31
|
+
|
|
32
|
+
if (isError) return <>Error</>;` : ''}
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<div className='flex gap-4 items-center justify-center my-8 mx-auto'>
|
|
36
|
+
<Image
|
|
37
|
+
className='dark:invert'
|
|
38
|
+
src='/imgs/next.svg'
|
|
39
|
+
alt='Next.js logo'
|
|
40
|
+
width={100}
|
|
41
|
+
height={20}
|
|
42
|
+
priority
|
|
43
|
+
/>
|
|
44
|
+
<P marginBottom='none'>&</P>
|
|
45
|
+
<Image
|
|
46
|
+
className='dark:invert'
|
|
47
|
+
src='/imgs/Tailwind_CSS_Logo.svg'
|
|
48
|
+
alt='Tailwind logo'
|
|
49
|
+
width={40}
|
|
50
|
+
height={20}
|
|
51
|
+
priority
|
|
52
|
+
/>
|
|
53
|
+
<P marginBottom='none'>&</P>
|
|
54
|
+
<Image
|
|
55
|
+
className='dark:invert'
|
|
56
|
+
src='/imgs/Zustand-logo.svg'
|
|
57
|
+
alt='Zustand logo'
|
|
58
|
+
width={40}
|
|
59
|
+
height={20}
|
|
60
|
+
priority
|
|
61
|
+
/>
|
|
62
|
+
<P marginBottom='none'>&</P>
|
|
63
|
+
<Image
|
|
64
|
+
className='dark:invert'
|
|
65
|
+
src='/imgs/undp-logo-blue.svg'
|
|
66
|
+
alt='UNDP logo'
|
|
67
|
+
width={40}
|
|
68
|
+
height={20}
|
|
69
|
+
priority
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
<P marginBottom='xl' className='text-center'>
|
|
73
|
+
To get started, edit the App.tsx file.{' '}
|
|
74
|
+
<span className='font-bold'>Count: {count}</span>
|
|
75
|
+
</P>
|
|
76
|
+
<div className='flex gap-4 justify-center mb-8'>
|
|
77
|
+
<Button
|
|
78
|
+
variant='tertiary'
|
|
79
|
+
onClick={() => {
|
|
80
|
+
increment();
|
|
81
|
+
}}
|
|
82
|
+
>
|
|
83
|
+
Increase counter
|
|
84
|
+
</Button>
|
|
85
|
+
<Button
|
|
86
|
+
variant='tertiary'
|
|
87
|
+
onClick={() => {
|
|
88
|
+
decrement();
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
Decrease counter
|
|
92
|
+
</Button>
|
|
93
|
+
</div>${query ? `
|
|
94
|
+
<P marginBottom='xl' className='text-center'>
|
|
95
|
+
Data loaded successfully. {data?.length} elements in the query.
|
|
96
|
+
</P>` : ''}
|
|
97
|
+
</>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
`
|
|
101
|
+
}
|
|
102
|
+
|
|
@@ -6,3 +6,5 @@ export { generateLayoutForNext } from './generateLayoutForNext.js';
|
|
|
6
6
|
export { generateStylesCss } from './generateStylesCss.js';
|
|
7
7
|
export { generateNextEnvTypes } from './generateNextEnvTypes.js';
|
|
8
8
|
export { generateEnv } from './generateEnv.js';
|
|
9
|
+
export { generatePageForNext } from './generatePageForNext.js';
|
|
10
|
+
export { generateGitIgnore } from './generateGitIgnore.js';
|
package/bin/index.js
CHANGED
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
generateLayoutForNext,
|
|
18
18
|
generateNextEnvTypes,
|
|
19
19
|
generateEnv,
|
|
20
|
+
generatePageForNext,
|
|
21
|
+
generateGitIgnore,
|
|
20
22
|
} from './generateFiles/index.js';
|
|
21
23
|
|
|
22
24
|
function copyFolder(source, destination) {
|
|
@@ -45,14 +47,17 @@ async function main() {
|
|
|
45
47
|
let tertiaryFolder = 'basic';
|
|
46
48
|
|
|
47
49
|
switch (config.framework) {
|
|
48
|
-
case 'vite-
|
|
49
|
-
|
|
50
|
+
case 'vite-basic':
|
|
51
|
+
if (config.query)
|
|
52
|
+
tertiaryFolder = 'query';
|
|
53
|
+
else
|
|
54
|
+
tertiaryFolder = 'basic';
|
|
50
55
|
break;
|
|
51
56
|
case 'vite-router':
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
if (config.query)
|
|
58
|
+
tertiaryFolder = 'query+router';
|
|
59
|
+
else
|
|
60
|
+
tertiaryFolder = 'router';
|
|
56
61
|
break;
|
|
57
62
|
case 'next-auth':
|
|
58
63
|
tertiaryFolder = 'auth';
|
|
@@ -73,10 +78,13 @@ async function main() {
|
|
|
73
78
|
}
|
|
74
79
|
} else {
|
|
75
80
|
copyFolder(path.join(__dirname, `./templates/${baseFolder}/${tertiaryFolder}`), projectPath);
|
|
76
|
-
fs.writeFileSync('app/layout.tsx', generateLayoutForNext(config.libraries.includes('@undp/data-viz'), config.projectName));
|
|
81
|
+
fs.writeFileSync('app/layout.tsx', generateLayoutForNext(config.libraries.includes('@undp/data-viz'), config.projectName, config.query));
|
|
77
82
|
fs.writeFileSync('next-env.d.ts', generateNextEnvTypes());
|
|
83
|
+
fs.writeFileSync('app/page.tsx', generatePageForNext(config.query));
|
|
78
84
|
if (config.framework === 'next-auth') fs.writeFileSync('.env.local', generateEnv());
|
|
85
|
+
if (config.query) copyFolder(path.join(__dirname, './templates/queryIntegrationForNext'), projectPath);
|
|
79
86
|
}
|
|
87
|
+
fs.writeFileSync('.gitignore', generateGitIgnore(config.framework.includes('vite')));
|
|
80
88
|
fs.writeFileSync('package.json', JSON.stringify(generatePackageJson(config), null, 2));
|
|
81
89
|
|
|
82
90
|
console.log(chalk.green(' β Project folder and files generated\n'));
|
package/bin/promptUser.js
CHANGED
|
@@ -25,17 +25,29 @@ export async function promptUser(name) {
|
|
|
25
25
|
loop: false,
|
|
26
26
|
message: chalk.yellow('π¦ Choose your setup (all include Tailwind for styling & Zustand for state management):\n'),
|
|
27
27
|
choices: [
|
|
28
|
-
{ name: 'Vite β Basic React setup', value: 'vite-basic' },
|
|
29
|
-
{ name: 'Vite + Query β With TanStack Query', value: 'vite-query' },
|
|
28
|
+
{ name: 'Vite β Basic React setup (ideal for embedding)', value: 'vite-basic' },
|
|
30
29
|
{ name: 'Vite + Router β With routing support', value: 'vite-router' },
|
|
31
|
-
{ name: 'Vite + Router + Query β Full Vite setup', value: 'vite-full' },
|
|
32
30
|
{ name: 'Next.js β SSR and file routing', value: 'next-basic' },
|
|
33
31
|
{ name: 'Next.js + Auth β With authentication', value: 'next-auth' },
|
|
34
32
|
],
|
|
35
33
|
default: 'vite-basic',
|
|
36
34
|
},
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const { addQuery } = await inquirer.prompt([
|
|
38
|
+
{
|
|
39
|
+
type: 'list',
|
|
40
|
+
name: 'addQuery',
|
|
41
|
+
message: chalk.yellow(
|
|
42
|
+
'βοΈ Add @tanstack/query for data fetching?'
|
|
43
|
+
),
|
|
44
|
+
choices: ['Yes', 'No'],
|
|
45
|
+
default: 'No',
|
|
46
|
+
},
|
|
37
47
|
]);
|
|
38
48
|
|
|
49
|
+
const query = addQuery === 'Yes';
|
|
50
|
+
|
|
39
51
|
const libraryChoices = [
|
|
40
52
|
{
|
|
41
53
|
name: '@undp/data-viz β UNDP data visualization components',
|
|
@@ -97,6 +109,7 @@ export async function promptUser(name) {
|
|
|
97
109
|
libraries,
|
|
98
110
|
addStaticWebAppConfig,
|
|
99
111
|
addPostCSSScripts,
|
|
100
|
-
framework,
|
|
112
|
+
framework,
|
|
113
|
+
query,
|
|
101
114
|
};
|
|
102
115
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Metadata } from 'next';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
|
|
3
4
|
import HeaderEl from '@/components/Header';
|
|
4
5
|
import FooterEl from '@/components/Footer';
|
|
@@ -14,7 +15,7 @@ export const metadata: Metadata = {
|
|
|
14
15
|
export default function RootLayout({
|
|
15
16
|
children,
|
|
16
17
|
}: Readonly<{
|
|
17
|
-
children:
|
|
18
|
+
children: ReactNode;
|
|
18
19
|
}>) {
|
|
19
20
|
return (
|
|
20
21
|
<html lang='en'>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Metadata } from 'next';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
|
|
3
4
|
import HeaderEl from '@/components/Header';
|
|
4
5
|
import FooterEl from '@/components/Footer';
|
|
@@ -15,7 +16,7 @@ export const metadata: Metadata = {
|
|
|
15
16
|
export default function RootLayout({
|
|
16
17
|
children,
|
|
17
18
|
}: Readonly<{
|
|
18
|
-
children:
|
|
19
|
+
children: ReactNode;
|
|
19
20
|
}>) {
|
|
20
21
|
return (
|
|
21
22
|
<html lang='en'>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
4
|
+
import { ReactNode, useState } from 'react';
|
|
5
|
+
|
|
6
|
+
export default function TanStackQueryProvider({
|
|
7
|
+
children,
|
|
8
|
+
}: {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}) {
|
|
11
|
+
// Create client only once
|
|
12
|
+
const [queryClient] = useState(
|
|
13
|
+
() =>
|
|
14
|
+
new QueryClient({
|
|
15
|
+
defaultOptions: {
|
|
16
|
+
queries: {
|
|
17
|
+
staleTime: 1000 * 60 * 60 * 24, // how long fetched data is considered βfreshβ before it becomes βstaleβ π‘’ 24 hrs
|
|
18
|
+
gcTime: 1000 * 60 * 60 * 24, // how long inactive (unused) query data stays in memory before being deleted π‘’ 24 hrs
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
|
|
3
4
|
export function getContext() {
|
|
4
5
|
const queryClient = new QueryClient({
|
|
@@ -18,7 +19,7 @@ export function Provider({
|
|
|
18
19
|
children,
|
|
19
20
|
queryClient,
|
|
20
21
|
}: {
|
|
21
|
-
children:
|
|
22
|
+
children: ReactNode;
|
|
22
23
|
queryClient: QueryClient;
|
|
23
24
|
}) {
|
|
24
25
|
return (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
|
|
3
4
|
export function getContext() {
|
|
4
5
|
const queryClient = new QueryClient({
|
|
@@ -18,7 +19,7 @@ export function Provider({
|
|
|
18
19
|
children,
|
|
19
20
|
queryClient,
|
|
20
21
|
}: {
|
|
21
|
-
children:
|
|
22
|
+
children: ReactNode;
|
|
22
23
|
queryClient: QueryClient;
|
|
23
24
|
}) {
|
|
24
25
|
return (
|