import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/vi/functional-basic/Classes/Api - Quản lý yêu cầu (Static)'/>

# Lớp Api

Lớp `Api` là **Lớp chính (Tĩnh)** và đóng vai trò là điểm truy cập chính để quản lý các yêu cầu HTTP. Nó là một wrapper tĩnh bao quanh một `ApiInstance` được quản lý toàn cục, cung cấp một giao diện singleton sạch sẽ cho các hoạt động mạng tiêu chuẩn.

## Các tính năng chính

- **Giao diện tĩnh** — thực hiện các hoạt động HTTP tiêu chuẩn (`GET`, `POST`, v.v.) mà không cần khởi tạo thủ công.
- **Hook vòng đời toàn cục** — cấu hình việc chuẩn bị và phân tích yêu cầu một lần cho toàn bộ ứng dụng.
- **Cách ly SSR** — sử dụng `ServerStorage` để quản lý việc cách ly các instance riêng lẻ trong quá trình render phía máy chủ.
- **Thiết lập đơn giản** — cung cấp phương thức `setConfig` thống nhất để áp dụng nhiều lớp cấu hình cùng một lúc.

## Các phương thức

### Hành động

Các phương thức để thực hiện các yêu cầu mạng vật lý.

- `request<T>(pathRequest: string | ApiFetch): Promise<T>` — Trình thực thi cốt lõi; chấp nhận một chuỗi đường dẫn hoặc đối tượng cấu hình.
- `get<T>(request: ApiFetch): Promise<T>` — Gửi yêu cầu GET.
- `post<T>(request: ApiFetch): Promise<T>` — Gửi yêu cầu POST.
- `put<T>(request: ApiFetch): Promise<T>` — Gửi yêu cầu PUT.
- `patch<T>(request: ApiFetch): Promise<T>` — Gửi yêu cầu PATCH.
- `delete<T>(request: ApiFetch): Promise<T>` — Gửi yêu cầu DELETE.

### Kiểm tra

- `isLocalhost(): boolean` — Kiểm tra xem môi trường hiện tại có phải là máy chủ phát triển cục bộ hay không.

### Cấu hình

- `setUrl(url: string): void` — Thay đổi URL base của API.
- `setHeaders(headers: Record<string, string>): void` — Thiết lập các header yêu cầu mặc định.
- `setRequestDefault(request: Record<string, any>): void` — Thiết lập dữ liệu body yêu cầu mặc định.
- `setPreparation(callback): void` — Đăng ký một hook để chạy trước mỗi yêu cầu được bật.
- `setEnd(callback): void` — Đăng ký một hook để chạy sau mỗi phản hồi được bật.
- `setTimeout(timeout: number): void` — Thay đổi timeout yêu cầu toàn cục.
- `setOrigin(origin: string): void` — Thay đổi nguồn (giao thức và tên miền) cho URL base.
- `setConfig(config?: ApiConfig): void` — Áp dụng một đối tượng cấu hình đầy đủ.

### Phụ trợ

- `getStatus(): ApiStatus` — Truy cập trình quản lý trạng thái cho yêu cầu cuối cùng.
- `getResponse(): ApiResponse` — Truy cập trình quản lý phản hồi/mô phỏng.
- `getHydration(): ApiHydration` — Truy cập trình quản lý hydration.
- `getHydrationScript(): string` — Trả về khối script để hydration từ SSR sang client.
- `getOrigin(): string` — Trả về URL base đã kết hợp với đường dẫn API.
- `getUrl(path: string, api?: boolean): string` — Trả về URL đã được phân giải đầy đủ với các token bản địa hóa.
- `getBody(request?, method?): string | FormData | undefined` — Chuẩn bị body yêu cầu.
- `getBodyForGet(request, path?, method?): string` — Chuẩn bị chuỗi truy vấn (query string).
- `getItem(): ApiInstance` — Trả về đối tượng `ApiInstance` cơ sở.

## Các kiểu dữ liệu (Types)

### ApiConfig

- `urlRoot: string` — URL base cho API.
- `origin: string` — giao thức và tên miền cho URL base.
- `headers: Record<string, string>` — các header yêu cầu mặc định.
- `requestDefault: Record<string, any>` — dữ liệu yêu cầu mặc định.
- `preparation: (apiFetch: ApiFetch) => Promise<void>` — hook đầu vào (entry hook).
- `end: (query: Response, apiFetch: ApiFetch) => Promise<ApiPreparationEnd>` — hook đầu ra (exit hook).
- `timeout: number` — timeout toàn cục tính bằng mili giây.

## Kiến trúc Proxy

Lớp `Api` hoạt động như một **Proxy tĩnh**. Tất cả các lệnh gọi phương thức đều được chuyển hướng đến một `ApiInstance` nội bộ.

### Quản lý Instance

Trình quản lý nội bộ được lưu trữ trong `ServerStorage` bằng một khóa duy nhất (`__dxt_api_instance__`). Kiến trúc này giải quyết hai vấn đề lớn:

1.  **An toàn luồng trong SSR**: Trong quá trình render phía máy chủ, `ServerStorage` đảm bảo rằng mỗi yêu cầu đến có cấu hình và trạng thái API riêng biệt, ngăn chặn rò rỉ dữ liệu giữa các người dùng.
2.  **Sự đơn giản của Singleton trên Client**: Ở phía client, nó hoạt động như một singleton thực sự, cho phép bạn cấu hình API tại điểm truy cập và sử dụng nó ở bất cứ đâu mà không cần truyền instance.

### Ủy quyền (Delegation)

Mặc dù `Api` là giao diện được ưu tiên cho logic ứng dụng tiêu chuẩn, nhưng logic cốt lõi (thử lại, logic hydration, jitter) nằm bên trong `ApiInstance`. Đối với các tình huống nâng cao liên quan đến nhiều URL base hoặc các bộ header khác nhau đồng thời, bạn có thể khởi tạo `ApiInstance` trực tiếp.
