diff --git a/README.md b/README.md index 5f80552..7ea9017 100644 --- a/README.md +++ b/README.md @@ -212,39 +212,79 @@ toaster.error({ title: "Error", description: "Something went wrong." }); --- -## 📡 API Integration +## 📡 API Integration (Standard Architecture) -### Creating API Clients +The project follows a strict **Service + Hook** pattern for API integration to ensure separation of concerns, type safety, and efficient caching. -```tsx -// src/lib/api/auth/login/queries.ts -import { createApiClient } from "../create-api-client"; +**🏆 Golden Standard Reference:** [`src/lib/api/example`](src/lib/api/example) -const api = createApiClient("/api/backend/auth"); +### 🏗️ Architecture Pattern -export const loginUser = async (data: LoginDto) => { - const response = await api.post("/login", data); - return response.data; +For every domain (e.g., `auth`, `users`), we strictly follow this 4-layer structure: + +| Layer | File | Purpose | +|-------|------|---------| +| **1. Types** | `types.ts` | **Contract:** pure TypeScript interfaces/DTOs matching Backend. | +| **2. Service** | `service.ts` | **Logic:** Pure functions calling `apiRequest`. Independent of React. | +| **3. Hooks** | `use-hooks.ts` | **State:** React Query wrappers (`useQuery`, `useMutation`) for caching & state. | +| **4. Barrel** | `index.ts` | **Public API:** Central export point for the module. | + +### 📝 Implementation Guide + +#### 1. Define Service (`service.ts`) +Uses `apiRequest` wrapper which handles client selection (`auth`, `core`, etc.), base URLs, and error normalization. + +```ts +// src/lib/api/example/auth/service.ts +import { apiRequest } from "@/lib/api/api-service"; +import { LoginDto, AuthResponse } from "./types"; + +const login = (data: LoginDto) => { + return apiRequest>({ + url: "/auth/login", + client: "auth", // Selects the correct axios instance from clientMap + method: "post", + data, + }); }; + +export const authService = { login }; ``` -### React Query Integration +#### 2. Create Hook (`use-hooks.ts`) +Wraps service in TanStack Query for loading states, caching, and invalidation. + +```ts +// src/lib/api/example/auth/use-hooks.ts +import { useMutation } from "@tanstack/react-query"; +import { authService } from "./service"; + +export const AuthQueryKeys = { + all: ["auth"] as const, +}; + +export function useLogin() { + return useMutation({ + mutationFn: (data: LoginDto) => authService.login(data), + }); +} +``` + +#### 3. Use in Components +Components only interact with the Hooks, never the Service or Axios directly. ```tsx -import { useQuery, useMutation } from "@tanstack/react-query"; +import { useLogin } from "@/lib/api/example"; // Import from barrel -// Query hook -export const useUsers = () => - useQuery({ - queryKey: ["users"], - queryFn: () => apiClient.get("/users"), - }); +export function LoginForm() { + const { mutate, isPending } = useLogin(); -// Mutation hook -export const useCreateUser = () => - useMutation({ - mutationFn: (data: CreateUserDto) => apiClient.post("/users", data), - }); + const handleSubmit = (data) => { + mutate(data, { + onSuccess: () => console.log("Logged in!"), + }); + }; +} ``` --- diff --git a/package.json b/package.json index 981cfab..1187579 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "scripts": { - "dev": "next dev --webpack --experimental-https -p 3001", + "dev": "next dev --webpack -p 3001", "build": "next build --webpack", "start": "next start", "lint": "eslint" @@ -41,4 +41,4 @@ "typescript": "^5" }, "description": "Generated by Frontend CLI" -} +} \ No newline at end of file