create-reactivite 1.1.0 → 1.2.0

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.
Files changed (55) hide show
  1. package/README.md +198 -197
  2. package/index.js +26 -1
  3. package/package.json +4 -3
  4. package/template/_gitignore +24 -0
  5. package/template2/.env.example +8 -0
  6. package/template2/.husky/pre-commit +4 -0
  7. package/template2/.prettierrc +5 -0
  8. package/template2/README.md +73 -0
  9. package/template2/__tests__/example.test.ts +20 -0
  10. package/template2/_gitignore +37 -0
  11. package/template2/app/[locale]/(private)/dashboard/page.tsx +52 -0
  12. package/template2/app/[locale]/(public)/login/page.tsx +83 -0
  13. package/template2/app/[locale]/layout.tsx +56 -0
  14. package/template2/app/[locale]/locales.ts +10 -0
  15. package/template2/app/[locale]/page.tsx +38 -0
  16. package/template2/app/api/clear-session/route.ts +10 -0
  17. package/template2/app/globals.css +127 -0
  18. package/template2/app/layout.tsx +7 -0
  19. package/template2/app/page.tsx +6 -0
  20. package/template2/components/AuthEventListener.tsx +22 -0
  21. package/template2/components/theme-provider.tsx +78 -0
  22. package/template2/components/ui/button.tsx +60 -0
  23. package/template2/components/ui/card.tsx +92 -0
  24. package/template2/components/ui/input.tsx +21 -0
  25. package/template2/components/ui/label.tsx +24 -0
  26. package/template2/components/ui/sonner.tsx +40 -0
  27. package/template2/components.json +22 -0
  28. package/template2/config/constants.ts +7 -0
  29. package/template2/config/env.ts +5 -0
  30. package/template2/contexts/translation-context.tsx +70 -0
  31. package/template2/eslint.config.mjs +18 -0
  32. package/template2/hoc/provider.tsx +27 -0
  33. package/template2/lib/paramsSerializer.ts +40 -0
  34. package/template2/lib/utils.ts +6 -0
  35. package/template2/locales/az.json +20 -0
  36. package/template2/locales/en.json +20 -0
  37. package/template2/next-env.d.ts +6 -0
  38. package/template2/next.config.ts +17 -0
  39. package/template2/orval.config.ts +66 -0
  40. package/template2/package.json +62 -0
  41. package/template2/pnpm-lock.yaml +6804 -0
  42. package/template2/postcss.config.mjs +7 -0
  43. package/template2/public/.gitkeep +0 -0
  44. package/template2/scripts/fix-generated-types.mjs +13 -0
  45. package/template2/services/generated/.gitkeep +2 -0
  46. package/template2/services/httpClient/httpClient.ts +70 -0
  47. package/template2/services/httpClient/orvalMutator.ts +10 -0
  48. package/template2/store/example-store.tsx +16 -0
  49. package/template2/store/user-store.tsx +29 -0
  50. package/template2/testing/msw/handlers/index.ts +6 -0
  51. package/template2/testing/msw/server.ts +4 -0
  52. package/template2/tsconfig.json +34 -0
  53. package/template2/tsconfig.tsbuildinfo +1 -0
  54. package/template2/vitest.config.ts +17 -0
  55. package/template2/vitest.setup.ts +7 -0
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
File without changes
@@ -0,0 +1,13 @@
1
+ // Post-processing hook for orval output.
2
+ // Runs after `npm run generate`. Add codemods here if your backend schema needs
3
+ // tweaks the generator can't express. No-op when nothing is generated yet.
4
+ import { existsSync } from 'node:fs';
5
+
6
+ const GENERATED_DIR = new URL('../services/generated/', import.meta.url);
7
+
8
+ if (!existsSync(GENERATED_DIR)) {
9
+ console.log('fix-generated-types: services/generated yox, keçildi.');
10
+ process.exit(0);
11
+ }
12
+
13
+ console.log('fix-generated-types: generated tipləri yoxlandı (no-op).');
@@ -0,0 +1,2 @@
1
+ # orval writes generated react-query hooks + models here.
2
+ # Run `npm run generate:api` after pointing orval.config.ts at your schema.
@@ -0,0 +1,70 @@
1
+ import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';
2
+ import { toast } from 'sonner';
3
+ import { useUserStore } from '@/store/user-store';
4
+ import { env } from '@/config/env';
5
+ import { AXIOS_TIMEOUT_MS } from '@/config/constants';
6
+ import { paramsSerializer } from '@/lib/paramsSerializer';
7
+
8
+ export const httpClient: AxiosInstance = axios.create({
9
+ baseURL: env.apiBaseUrl,
10
+ withCredentials: true,
11
+ paramsSerializer,
12
+ });
13
+
14
+ httpClient.defaults.timeout = AXIOS_TIMEOUT_MS;
15
+
16
+ type ServerErrorData = { message: string };
17
+
18
+ const errorMessageByCode: Record<number, string> = {
19
+ 400: 'Validation error',
20
+ 404: 'Not found',
21
+ 500: 'Server error',
22
+ };
23
+
24
+ const setupInterceptors = () => {
25
+ httpClient.interceptors.request.use(
26
+ (requestConfig) => {
27
+ if (typeof window !== 'undefined') {
28
+ const locale =
29
+ document.cookie.match(/NEXT_LOCALE=([^;]+)/)?.[1] ?? 'az';
30
+ requestConfig.headers['Accept-Language'] = locale;
31
+ }
32
+ return requestConfig;
33
+ },
34
+ (error: AxiosError) => Promise.reject(error),
35
+ );
36
+
37
+ httpClient.interceptors.response.use(
38
+ (response: AxiosResponse) => response,
39
+ (error: AxiosError) => {
40
+ if (error.response) {
41
+ const errorStatus = error.response.status;
42
+ const errorData = error.response.data as ServerErrorData;
43
+
44
+ if (errorStatus === 401 || errorStatus === 403) {
45
+ const store = useUserStore.getState();
46
+ if (store.isAuthenticated()) {
47
+ store.clearUser();
48
+ window.dispatchEvent(new CustomEvent('auth:unauthorized'));
49
+ }
50
+ return Promise.reject(error);
51
+ }
52
+
53
+ if (errorStatus in errorMessageByCode) {
54
+ toast.error(errorData?.message ?? errorMessageByCode[errorStatus]);
55
+ } else if (errorData?.message) {
56
+ toast.error(errorData.message);
57
+ } else {
58
+ toast.error(`Server status ${errorStatus}`);
59
+ }
60
+ } else if (error.request) {
61
+ toast.error('Network error. Check your connection.');
62
+ } else {
63
+ toast.error(`Unexpected error: ${error.message}`);
64
+ }
65
+ return Promise.reject(error);
66
+ },
67
+ );
68
+ };
69
+
70
+ setupInterceptors();
@@ -0,0 +1,10 @@
1
+ import { AxiosRequestConfig } from 'axios';
2
+ import { httpClient } from './httpClient';
3
+
4
+ export const customMutator = <T>(config: AxiosRequestConfig): Promise<T> => {
5
+ const { signal, ...rest } = config;
6
+ return httpClient({
7
+ ...rest,
8
+ ...(signal instanceof AbortSignal ? { signal } : {}),
9
+ }).then(({ data }) => data);
10
+ };
@@ -0,0 +1,16 @@
1
+ import { create } from 'zustand';
2
+
3
+ type CounterState = {
4
+ count: number;
5
+ increment: () => void;
6
+ decrement: () => void;
7
+ reset: () => void;
8
+ };
9
+
10
+ // Minimal store to show the non-persisted pattern. Delete or replace.
11
+ export const useExampleStore = create<CounterState>((set) => ({
12
+ count: 0,
13
+ increment: () => set((s) => ({ count: s.count + 1 })),
14
+ decrement: () => set((s) => ({ count: s.count - 1 })),
15
+ reset: () => set({ count: 0 }),
16
+ }));
@@ -0,0 +1,29 @@
1
+ import { create } from 'zustand';
2
+ import { persist } from 'zustand/middleware';
3
+
4
+ export type User = {
5
+ id: string;
6
+ email: string;
7
+ fullName?: string;
8
+ };
9
+
10
+ type UserState = {
11
+ user: User | null;
12
+ setUser: (value: User | null) => void;
13
+ clearUser: () => void;
14
+ isAuthenticated: () => boolean;
15
+ };
16
+
17
+ export const useUserStore = create<UserState>()(
18
+ persist(
19
+ (set, get) => ({
20
+ user: null,
21
+ setUser: (value) => set({ user: value }),
22
+ clearUser: () => set({ user: null }),
23
+ isAuthenticated: () => get().user !== null,
24
+ }),
25
+ {
26
+ name: 'user_authenticated',
27
+ },
28
+ ),
29
+ );
@@ -0,0 +1,6 @@
1
+ import { http, HttpResponse } from 'msw';
2
+
3
+ // Add request handlers here. Example:
4
+ export const handlers = [
5
+ http.get('*/health', () => HttpResponse.json({ status: 'ok' })),
6
+ ];
@@ -0,0 +1,4 @@
1
+ import { setupServer } from 'msw/node';
2
+ import { handlers } from './handlers';
3
+
4
+ export const server = setupServer(...handlers);
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": [
26
+ "next-env.d.ts",
27
+ "**/*.ts",
28
+ "**/*.tsx",
29
+ ".next/types/**/*.ts",
30
+ ".next/dev/types/**/*.ts",
31
+ "**/*.mts"
32
+ ],
33
+ "exclude": ["node_modules"]
34
+ }