@aditokmo/react-setup-cli 0.1.0 → 0.1.1
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/dist/index.js +13 -6
- package/dist/installers.js +10 -3
- package/dist/mapper.js +2 -1
- package/dist/packages.js +3 -4
- package/dist/questions.js +26 -1
- package/dist/utils.js +8 -0
- package/package.json +1 -1
- package/templates/base/src/modules/auth/hooks/useAuth.ts +49 -37
- package/templates/base/src/modules/common/pages/NotFound.tsx +12 -7
- package/templates/base/src/styles/404.css +105 -0
- package/templates/state/react-query/src/hook/useAuth.ts +43 -0
- package/templates/state/react-query/src/{ReactQueryProvider.tsx → provider/ReactQueryProvider.tsx} +10 -3
- package/templates/base/pnpm-lock.yaml +0 -2105
- /package/templates/state/react-query/src/{index.ts → provider/index.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import fs from 'fs-extra';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { execSync } from 'child_process';
|
|
5
5
|
import { askQuestions } from './questions.js';
|
|
6
|
-
import { copyTemplate, patchViteConfig, finalizeViteConfig, patchAppFile, finalizeAppFile } from './utils.js';
|
|
6
|
+
import { copyTemplate, patchViteConfig, finalizeViteConfig, patchAppFile, finalizeAppFile, detectPackageManager } from './utils.js';
|
|
7
7
|
import { collectDependencies } from './installers.js';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -11,8 +11,11 @@ const __dirname = path.dirname(__filename);
|
|
|
11
11
|
async function main() {
|
|
12
12
|
console.log('⚛️ Welcome to React CLI Setup by github/aditokmo');
|
|
13
13
|
let projectDir = '';
|
|
14
|
+
const originalDirectory = process.cwd();
|
|
14
15
|
try {
|
|
15
16
|
const answers = await askQuestions();
|
|
17
|
+
const packageManager = detectPackageManager();
|
|
18
|
+
const installAction = packageManager === 'yarn' ? 'add' : 'install';
|
|
16
19
|
projectDir = path.join(process.cwd(), answers.projectName);
|
|
17
20
|
const templateRoot = path.join(__dirname, '../templates');
|
|
18
21
|
const appFilePath = path.join(projectDir, 'src', 'App.tsx');
|
|
@@ -29,7 +32,8 @@ async function main() {
|
|
|
29
32
|
}
|
|
30
33
|
// State Management
|
|
31
34
|
if (answers.reactQuery) {
|
|
32
|
-
copyTemplate(path.join(templateRoot, 'state', 'react-query', 'src'), path.join(projectDir, 'src/providers'));
|
|
35
|
+
copyTemplate(path.join(templateRoot, 'state', 'react-query', 'src', 'provider'), path.join(projectDir, 'src/providers'));
|
|
36
|
+
copyTemplate(path.join(templateRoot, 'state', 'react-query', 'src', 'hook'), path.join(projectDir, 'src/modules/auth/hooks'));
|
|
33
37
|
patchAppFile(appFilePath, "import { ReactQueryProvider } from './providers'", "<ReactQueryProvider>", "</ReactQueryProvider>");
|
|
34
38
|
}
|
|
35
39
|
if (answers.globalState === 'zustand') {
|
|
@@ -50,15 +54,17 @@ async function main() {
|
|
|
50
54
|
}
|
|
51
55
|
finalizeAppFile(appFilePath);
|
|
52
56
|
finalizeViteConfig(viteConfigPath);
|
|
53
|
-
const { dependency, devDependency, cmd } = collectDependencies(answers);
|
|
57
|
+
const { dependency, devDependency, cmd } = collectDependencies(answers, packageManager);
|
|
54
58
|
process.chdir(projectDir);
|
|
59
|
+
console.log(`📦 Initializing ${packageManager} project...`);
|
|
60
|
+
execSync(`${packageManager} install`, { stdio: 'inherit' });
|
|
55
61
|
if (dependency.length) {
|
|
56
62
|
console.log('📦 Installing dependencies...');
|
|
57
|
-
execSync(
|
|
63
|
+
execSync(`${packageManager} ${installAction} ${dependency.join(' ')}`, { stdio: 'inherit' });
|
|
58
64
|
}
|
|
59
65
|
if (devDependency.length) {
|
|
60
66
|
console.log('📦 Installing dev dependencies...');
|
|
61
|
-
execSync(
|
|
67
|
+
execSync(`${packageManager} ${installAction} -D ${devDependency.join(' ')}`, { stdio: 'inherit' });
|
|
62
68
|
}
|
|
63
69
|
// Extra cmds like shadcn
|
|
64
70
|
for (const command of cmd) {
|
|
@@ -66,11 +72,12 @@ async function main() {
|
|
|
66
72
|
execSync(command, { stdio: 'inherit' });
|
|
67
73
|
}
|
|
68
74
|
console.log('✅ Project setup completed');
|
|
69
|
-
console.log(`👉 cd ${answers.projectName} &&
|
|
75
|
+
console.log(`👉 cd ${answers.projectName} && ${packageManager} run dev`);
|
|
70
76
|
}
|
|
71
77
|
catch (error) {
|
|
72
78
|
console.error('\n❌ Error while creating a project:');
|
|
73
79
|
console.error(`👉 ${error.message}`);
|
|
80
|
+
process.chdir(originalDirectory);
|
|
74
81
|
if (projectDir && fs.existsSync(projectDir)) {
|
|
75
82
|
console.log('🧹 Cleaning... Deleting failed project installation.');
|
|
76
83
|
fs.removeSync(projectDir);
|
package/dist/installers.js
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { installers } from './mapper.js';
|
|
2
|
-
import { axiosInstaller
|
|
3
|
-
export function collectDependencies(answers) {
|
|
2
|
+
import { axiosInstaller } from './packages.js';
|
|
3
|
+
export function collectDependencies(answers, packageManager) {
|
|
4
4
|
const dependency = new Set();
|
|
5
5
|
const devDependency = new Set();
|
|
6
6
|
const cmd = [];
|
|
7
|
+
const dlx = packageManager === 'npm' ? 'npx --yes' : `${packageManager} dlx --yes`;
|
|
7
8
|
// Default base packages
|
|
8
9
|
axiosInstaller.dependency?.forEach(d => dependency.add(d));
|
|
9
10
|
// Packages from answers
|
|
10
11
|
Object.entries(answers).forEach(([key, value]) => {
|
|
12
|
+
if (Array.isArray(value))
|
|
13
|
+
return;
|
|
11
14
|
const installer = installers[value === true ? key : value];
|
|
12
15
|
installer?.dependency?.forEach(d => dependency.add(d));
|
|
13
16
|
installer?.devDependency?.forEach(d => devDependency.add(d));
|
|
14
17
|
});
|
|
15
18
|
if (answers.shadcn && answers.style === 'tailwind') {
|
|
16
|
-
cmd.push(
|
|
19
|
+
cmd.push(`${dlx} shadcn@latest init -d`);
|
|
20
|
+
if (answers.shadcnComponents && answers.shadcnComponents.length > 0) {
|
|
21
|
+
const componentsStr = answers.shadcnComponents.join(' ');
|
|
22
|
+
cmd.push(`${dlx} shadcn@latest add ${componentsStr} -y -o`);
|
|
23
|
+
}
|
|
17
24
|
}
|
|
18
25
|
return {
|
|
19
26
|
dependency: Array.from(dependency),
|
package/dist/mapper.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fontAwesomeIconsInstaller, reactFormHookInstaller, reactHotToastInstaller, reactIconsInstaller, reactQueryInstaller, reactRouterInstaller, reactToastifyInstaller, sonnerInstaller, tailwindInstaller, tanstackFormInstaller, tanstackRouterInstaller, yupInstaller, zodInstaller, zustandInstaller } from './packages.js';
|
|
1
|
+
import { fontAwesomeIconsInstaller, phosphorIconsInstaller, reactFormHookInstaller, reactHotToastInstaller, reactIconsInstaller, reactQueryInstaller, reactRouterInstaller, reactToastifyInstaller, sonnerInstaller, tailwindInstaller, tanstackFormInstaller, tanstackRouterInstaller, yupInstaller, zodInstaller, zustandInstaller } from './packages.js';
|
|
2
2
|
export const installers = {
|
|
3
3
|
'reactQuery': reactQueryInstaller,
|
|
4
4
|
'zustand': zustandInstaller,
|
|
@@ -7,6 +7,7 @@ export const installers = {
|
|
|
7
7
|
'tailwind': tailwindInstaller,
|
|
8
8
|
'react-icons': reactIconsInstaller,
|
|
9
9
|
'font-awesome': fontAwesomeIconsInstaller,
|
|
10
|
+
'phosphor-icons': phosphorIconsInstaller,
|
|
10
11
|
'react-hot-toast': reactHotToastInstaller,
|
|
11
12
|
'react-toastify': reactToastifyInstaller,
|
|
12
13
|
'sonner': sonnerInstaller,
|
package/dist/packages.js
CHANGED
|
@@ -18,6 +18,9 @@ export const reactIconsInstaller = {
|
|
|
18
18
|
export const fontAwesomeIconsInstaller = {
|
|
19
19
|
dependency: ['@fortawesome/fontawesome-svg-core', '@fortawesome/react-fontawesome', '@fortawesome/free-solid-svg-icons', '@fortawesome/free-regular-svg-icons', '@fortawesome/free-brands-svg-icons'],
|
|
20
20
|
};
|
|
21
|
+
export const phosphorIconsInstaller = {
|
|
22
|
+
dependency: ['phosphor-react'],
|
|
23
|
+
};
|
|
21
24
|
// Toast
|
|
22
25
|
export const reactHotToastInstaller = {
|
|
23
26
|
dependency: ['react-hot-toast'],
|
|
@@ -28,10 +31,6 @@ export const reactToastifyInstaller = {
|
|
|
28
31
|
export const sonnerInstaller = {
|
|
29
32
|
dependency: ['sonner'],
|
|
30
33
|
};
|
|
31
|
-
// UI Libs
|
|
32
|
-
export const shadcnInstaller = {
|
|
33
|
-
cmd: ['pnpm dlx shadcn@latest init']
|
|
34
|
-
};
|
|
35
34
|
// Routers
|
|
36
35
|
export const reactRouterInstaller = {
|
|
37
36
|
dependency: ['react-router', 'react-router-dom'],
|
package/dist/questions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { group, text, select, confirm, isCancel, cancel } from '@clack/prompts';
|
|
1
|
+
import { group, text, select, confirm, isCancel, cancel, multiselect } from '@clack/prompts';
|
|
2
2
|
export async function askQuestions() {
|
|
3
3
|
const results = await group({
|
|
4
4
|
projectName: () => text({
|
|
@@ -18,11 +18,32 @@ export async function askQuestions() {
|
|
|
18
18
|
return Promise.resolve(false);
|
|
19
19
|
return confirm({ message: 'Include Shadcn UI?' });
|
|
20
20
|
},
|
|
21
|
+
shadcnComponents: ({ results }) => {
|
|
22
|
+
if (!results.shadcn)
|
|
23
|
+
return Promise.resolve([]);
|
|
24
|
+
return multiselect({
|
|
25
|
+
message: 'Use space to select shadcn/ui components to install:',
|
|
26
|
+
options: [
|
|
27
|
+
{ value: 'button', label: 'Button' },
|
|
28
|
+
{ value: 'input', label: 'Input' },
|
|
29
|
+
{ value: 'card', label: 'Card' },
|
|
30
|
+
{ value: 'dialog', label: 'Dialog' },
|
|
31
|
+
{ value: 'sheet', label: 'Sheet' },
|
|
32
|
+
{ value: 'dropdown-menu', label: 'Dropdown Menu' },
|
|
33
|
+
{ value: 'table', label: 'Table' },
|
|
34
|
+
{ value: 'checkbox', label: 'Checkbox' },
|
|
35
|
+
{ value: 'avatar', label: 'Avatar' },
|
|
36
|
+
{ value: 'badge', label: 'Badge' },
|
|
37
|
+
],
|
|
38
|
+
required: false,
|
|
39
|
+
});
|
|
40
|
+
},
|
|
21
41
|
icons: () => select({
|
|
22
42
|
message: 'Choose icon library:',
|
|
23
43
|
options: [
|
|
24
44
|
{ value: 'react-icons', label: 'React Icons' },
|
|
25
45
|
{ value: 'font-awesome', label: 'Font Awesome' },
|
|
46
|
+
{ value: 'phosphor-icons', label: 'Phosphor Icons' }
|
|
26
47
|
]
|
|
27
48
|
}),
|
|
28
49
|
toast: () => select({
|
|
@@ -71,6 +92,9 @@ export async function askQuestions() {
|
|
|
71
92
|
isCancel(results.style) ||
|
|
72
93
|
isCancel(results.router) ||
|
|
73
94
|
isCancel(results.shadcn) ||
|
|
95
|
+
isCancel(results.shadcnComponents) ||
|
|
96
|
+
isCancel(results.icons) ||
|
|
97
|
+
isCancel(results.toast) ||
|
|
74
98
|
isCancel(results.reactQuery)) {
|
|
75
99
|
cancel('Setup cancelled.');
|
|
76
100
|
process.exit(0);
|
|
@@ -78,5 +102,6 @@ export async function askQuestions() {
|
|
|
78
102
|
return {
|
|
79
103
|
...results,
|
|
80
104
|
shadcn: results.shadcn,
|
|
105
|
+
shadcnComponents: (results.shadcnComponents ?? []),
|
|
81
106
|
};
|
|
82
107
|
}
|
package/dist/utils.js
CHANGED
|
@@ -72,3 +72,11 @@ export function finalizeAppFile(filePath) {
|
|
|
72
72
|
.trim();
|
|
73
73
|
fs.writeFileSync(filePath, content + '\n');
|
|
74
74
|
}
|
|
75
|
+
export function detectPackageManager() {
|
|
76
|
+
const userAgent = process.env.npm_config_user_agent || '';
|
|
77
|
+
if (userAgent.includes('pnpm'))
|
|
78
|
+
return 'pnpm';
|
|
79
|
+
if (userAgent.includes('yarn'))
|
|
80
|
+
return 'yarn';
|
|
81
|
+
return 'npm';
|
|
82
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aditokmo/react-setup-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A fast React CLI to jumpstart your projects. It sets up your libraries and organizes a scalable folder structure so you can skip the configuration and go straight to coding.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -1,43 +1,55 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { getAPIErrorMessage } from "@/utils/api-error-handler";
|
|
2
|
-
import { AuthService } from "../services"
|
|
3
|
-
import { useMutation } from '@tanstack/react-query';
|
|
3
|
+
import { AuthService } from "../services";
|
|
4
4
|
|
|
5
5
|
export const useAuth = () => {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
onSuccess: (res) => {
|
|
9
|
-
// Handle mutation success
|
|
10
|
-
},
|
|
11
|
-
onError: (error) => {
|
|
12
|
-
const errorMessage = getAPIErrorMessage(error);
|
|
13
|
-
console.error(errorMessage)
|
|
14
|
-
// Display error message to user
|
|
15
|
-
},
|
|
16
|
-
});
|
|
6
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
7
|
+
const [error, setError] = useState<string | null>(null);
|
|
17
8
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
9
|
+
const login = async (data: any) => {
|
|
10
|
+
setIsLoading(true);
|
|
11
|
+
setError(null);
|
|
12
|
+
try {
|
|
13
|
+
const res = await AuthService.login(data);
|
|
14
|
+
return res;
|
|
15
|
+
} catch (err) {
|
|
16
|
+
const errorMessage = getAPIErrorMessage(err);
|
|
17
|
+
setError(errorMessage);
|
|
18
|
+
console.error(errorMessage);
|
|
19
|
+
throw err;
|
|
20
|
+
} finally {
|
|
21
|
+
setIsLoading(false);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
29
24
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
25
|
+
const register = async (data: any) => {
|
|
26
|
+
setIsLoading(true);
|
|
27
|
+
setError(null);
|
|
28
|
+
try {
|
|
29
|
+
const res = await AuthService.register(data);
|
|
30
|
+
return res;
|
|
31
|
+
} catch (err) {
|
|
32
|
+
const errorMessage = getAPIErrorMessage(err);
|
|
33
|
+
setError(errorMessage);
|
|
34
|
+
throw err;
|
|
35
|
+
} finally {
|
|
36
|
+
setIsLoading(false);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const logout = async () => {
|
|
41
|
+
try {
|
|
42
|
+
await AuthService.logout();
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error(getAPIErrorMessage(err));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
login,
|
|
50
|
+
register,
|
|
51
|
+
logout,
|
|
52
|
+
isLoading,
|
|
53
|
+
error
|
|
54
|
+
};
|
|
55
|
+
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import '@/styles/404.css';
|
|
2
|
+
|
|
3
|
+
export const NotFound = () => {
|
|
2
4
|
return (
|
|
3
|
-
<div className="
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
<div className="not-found-wrapper">
|
|
6
|
+
<div className="not-found-content">
|
|
7
|
+
<span>404</span>
|
|
8
|
+
<h1>Oops! Page Not Found</h1>
|
|
9
|
+
<p>The page you are looking for doesn't exist. Click button below to go to the homepage</p>
|
|
10
|
+
<a href="/">Back to Homepage</a>
|
|
11
|
+
</div>
|
|
7
12
|
</div>
|
|
8
|
-
)
|
|
9
|
-
}
|
|
13
|
+
);
|
|
14
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
.not-found-wrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
padding: 20px;
|
|
8
|
+
text-align: center;
|
|
9
|
+
font-family: "Poppins", sans-serif;
|
|
10
|
+
background: #e6edfc;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.not-found-content {
|
|
14
|
+
padding: 100px 70px;
|
|
15
|
+
background: #fff;
|
|
16
|
+
max-width: 700px;
|
|
17
|
+
width: 100%;
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
align-items: center;
|
|
22
|
+
border-radius: 24px;
|
|
23
|
+
box-shadow: 0px 0px 14px -14px rgba(0, 0, 0, 0.75);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.not-found-content span {
|
|
27
|
+
color: #666;
|
|
28
|
+
font-weight: 700;
|
|
29
|
+
font-size: 6rem;
|
|
30
|
+
line-height: 1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.not-found-content h1 {
|
|
34
|
+
font-size: 2.5rem;
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
margin: 0;
|
|
37
|
+
color: #111;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.not-found-content p {
|
|
41
|
+
font-size: 1rem;
|
|
42
|
+
color: #666;
|
|
43
|
+
max-width: 360px;
|
|
44
|
+
width: 100%;
|
|
45
|
+
margin: 10px 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.not-found-content a {
|
|
49
|
+
font-size: 0.9rem;
|
|
50
|
+
color: #fff;
|
|
51
|
+
background-color: #37538a;
|
|
52
|
+
padding: 10px 30px;
|
|
53
|
+
margin-top: 20px;
|
|
54
|
+
border-radius: 10px;
|
|
55
|
+
transition: 0.2s;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
text-decoration: none;
|
|
58
|
+
display: inline-block;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.not-found-content a:hover {
|
|
62
|
+
background: #263c67;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (max-width: 768px) {
|
|
66
|
+
.not-found-content {
|
|
67
|
+
padding: 60px 40px;
|
|
68
|
+
max-width: 90%;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.not-found-content span {
|
|
72
|
+
font-size: 4.5rem;
|
|
73
|
+
margin-bottom: 20px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.not-found-content h1 {
|
|
77
|
+
font-size: 2rem;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@media (max-width: 480px) {
|
|
82
|
+
.not-found-content {
|
|
83
|
+
padding: 40px 20px;
|
|
84
|
+
border-radius: 16px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.not-found-content span {
|
|
88
|
+
font-size: 3.5rem;
|
|
89
|
+
margin-bottom: 20px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.not-found-content h1 {
|
|
93
|
+
font-size: 1.5rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.not-found-content p {
|
|
97
|
+
font-size: 0.9rem;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.not-found-content a {
|
|
101
|
+
width: 100%;
|
|
102
|
+
box-sizing: border-box;
|
|
103
|
+
text-align: center;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { getAPIErrorMessage } from "@/utils/api-error-handler";
|
|
2
|
+
import { AuthService } from "../services"
|
|
3
|
+
import { useMutation } from '@tanstack/react-query';
|
|
4
|
+
|
|
5
|
+
export const useAuth = () => {
|
|
6
|
+
const login = useMutation({
|
|
7
|
+
mutationFn: AuthService.login,
|
|
8
|
+
onSuccess: (res) => {
|
|
9
|
+
// Handle mutation success
|
|
10
|
+
},
|
|
11
|
+
onError: (error) => {
|
|
12
|
+
const errorMessage = getAPIErrorMessage(error);
|
|
13
|
+
console.error(errorMessage)
|
|
14
|
+
// Display error message to user
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const register = useMutation({
|
|
19
|
+
mutationFn: AuthService.register,
|
|
20
|
+
onSuccess: (res) => {
|
|
21
|
+
// Handle mutation success
|
|
22
|
+
},
|
|
23
|
+
onError: (error) => {
|
|
24
|
+
const errorMessage = getAPIErrorMessage(error);
|
|
25
|
+
console.error(errorMessage)
|
|
26
|
+
// Display error message to user
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const logout = useMutation({
|
|
31
|
+
mutationFn: AuthService.logout,
|
|
32
|
+
onSuccess: (res) => {
|
|
33
|
+
// Handle mutation success
|
|
34
|
+
},
|
|
35
|
+
onError: (error) => {
|
|
36
|
+
const errorMessage = getAPIErrorMessage(error);
|
|
37
|
+
console.error(errorMessage)
|
|
38
|
+
// Display error message to user
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return { login, register, logout }
|
|
43
|
+
}
|
package/templates/state/react-query/src/{ReactQueryProvider.tsx → provider/ReactQueryProvider.tsx}
RENAMED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
-
import { QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
+
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
4
3
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
|
5
4
|
|
|
6
5
|
export function ReactQueryProvider({ children }: { children: React.ReactNode }) {
|
|
7
|
-
const [queryClient] = useState(() => new QueryClient(
|
|
6
|
+
const [queryClient] = useState(() => new QueryClient({
|
|
7
|
+
defaultOptions: {
|
|
8
|
+
queries: {
|
|
9
|
+
refetchOnWindowFocus: false,
|
|
10
|
+
retry: 1,
|
|
11
|
+
staleTime: 5 * 1000,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
8
15
|
|
|
9
16
|
return (
|
|
10
17
|
<QueryClientProvider client={queryClient}>
|