npm package: @sfutureapps/req-sdk
Description: Lightweight form-urlencoded request SDK with env auto-detect, optional X-API-Key, and token-in-body auth.
Author: sFutureApps
Latest version: 1.8.15

# @sfutureapps/req-sdk

> 🌐 Lightweight JavaScript SDK for making `application/x-www-form-urlencoded` API requests  
> Built for modern frameworks — Vite, React, Next.js, and Node.js — with automatic environment detection, token handling, and optional `X-API-Key` authentication.

---

## 🚀 Overview

`@sfutureapps/req-sdk` is a **simple yet powerful HTTP request wrapper** designed for apps that use `application/x-www-form-urlencoded` requests instead of JSON.

It automatically:

- Reads your API base URL from environment variables.
- Adds authentication tokens (from `localStorage` or `.env`) when required.
- Supports both **GET** and **POST** with clean named parameters.
- Works universally across **Vite**, **React**, **Next.js**, and **Node.js**.
- Encodes request bodies using `URLSearchParams`.

---

## ✨ Features

✅ Auto-detect environment (`VITE_`, `REACT_APP_`, `NEXT_PUBLIC_`, or Node).  
✅ Supports `application/x-www-form-urlencoded` requests.  
✅ Optional authentication (`IS_AUTH=true`) — token automatically merged into POST body.  
✅ Optional `X-API-Key` header when `API_KEY` is defined.  
✅ Automatic timeout and error handling.  
✅ Lightweight — no external dependencies.  
✅ TypeScript ready (`index.d.ts` included).

---

## 📦 Installation

```bash
npm i @sfutureapps/req-sdk
# or
yarn add @sfutureapps/req-sdk
```

---

## ⚙️ Environment Configuration

Set environment variables in your `.env` file depending on your framework:

### 🧩 Vite / React

```env
VITE_API_URL=https://api.example.com/v1
VITE_API_KEY=my-public-api-key
VITE_IS_AUTH=true
VITE_TOKEN_NAME=access_token
VITE_INCLUDE_TOKEN_IN_GET=true
```

### 🧩 Create React App

```env
REACT_APP_API_URL=https://api.example.com/v1
REACT_APP_API_KEY=my-public-api-key
REACT_APP_IS_AUTH=true
REACT_APP_TOKEN_NAME=access_token
```

### 🧩 Next.js (Client-Side)

```env
NEXT_PUBLIC_API_URL=https://api.example.com/v1
NEXT_PUBLIC_API_KEY=my-public-api-key
NEXT_PUBLIC_IS_AUTH=true
NEXT_PUBLIC_TOKEN_NAME=access_token
```

### 🧩 Node.js / Server-Side

```env
API_URL=https://api.example.com/v1
API_KEY=my-public-api-key
IS_AUTH=true
TOKEN_NAME=access_token
```

---

## 🧠 How It Works

The SDK checks for `API_URL` (or `BASE_URL`) automatically and validates it before sending requests.

If `IS_AUTH=true`, it retrieves the token from:

1. `localStorage[TOKEN_NAME]` (browser)
2. Environment variable with same name (server fallback)

When token exists:

- For **POST/PUT/PATCH/DELETE**, token is added to the **form body**.
- For **GET**, token is added as a **query parameter** (if `INCLUDE_TOKEN_IN_GET=true`).

If `API_KEY` is defined, it’s sent as an `X-API-Key` header automatically.

---

## 💻 Usage

Import and use directly in your app:

```ts
import post, { get } from "@sfutureapps/req-sdk";
```

### 🟢 GET Request

```ts
const users = await get({
  endpoint: "/users",
  params: { page: 1, q: "John" },
});

console.log(users);
```

### 🟢 POST Request

```ts
const login = await post({
  endpoint: "/auth/login",
  data: { username: "demo", password: "1234" },
});
```

### 🟢 POST with URL params + form data

```ts
const order = await post({
  endpoint: "/orders/create",
  params: { store_id: 10 },
  data: { product_id: 55, quantity: 2 },
});
```

---

## 🧾 Example Response

All responses are automatically parsed as JSON (if the server responds with `application/json`).

Example:

```json
{
  "status": "success",
  "data": {
    "id": 101,
    "username": "demo"
  }
}
```

---

## ⚠️ Error Handling

If a request fails (non-2xx), the SDK throws an error with details:

```ts
try {
  const result = await post({ endpoint: "/auth/login", data: { username: "bad", password: "wrong" } });
} catch (err) {
  console.error(err.message); // HTTP 401 Unauthorized
  console.error(err.body); // Server response body
}
```

---

## 🔐 Authentication Workflow

| Config                           | Behavior                                     |
| -------------------------------- | -------------------------------------------- |
| `IS_AUTH=false`                  | No token required.                           |
| `IS_AUTH=true` + token available | Automatically includes token.                |
| `IS_AUTH=true` + no token        | Throws: `Auth required but token not found`. |
| `API_KEY` set                    | Adds `X-API-Key` header automatically.       |

Example:

```http
POST /orders/create
Content-Type: application/x-www-form-urlencoded
X-API-Key: my-public-api-key

token=abcd1234&item_id=5&qty=2
```

---

## 🧩 TypeScript Support

The SDK ships with full type declarations.

```ts
import post, { get } from "@sfutureapps/req-sdk";

interface User {
  id: number;
  name: string;
}

const users = await get<User[]>({ endpoint: "/users" });
console.log(users[0].name);
```

Type Definitions:

```ts
export interface RequestParams {
  endpoint: string;
  data?: Record<string, any> | null;
  params?: Record<string, any>;
}

export default function post<T = any>(args: RequestParams): Promise<T>;
export function get<T = any>(args: Omit<RequestParams, "data">): Promise<T>;
```

---

## 🧪 Testing in Node.js

```bash
API_URL=https://api.example.com/v1 node test.js
```

**test.js**

```js
import post from "@sfutureapps/req-sdk";

const res = await post({
  endpoint: "/ping",
  data: { message: "Hello" },
});
console.log(res);
```

---

## 🧰 Environment Variable Priority

| Order | Key                   | Example |
| ----- | --------------------- | ------- |
| 1     | `API_URL`             | Node    |
| 2     | `NEXT_PUBLIC_API_URL` | Next.js |
| 3     | `VITE_API_URL`        | Vite    |
| 4     | `REACT_APP_API_URL`   | CRA     |
| 5     | `window.ENV.API_URL`  | Browser |

---

## 🧩 Advanced: Disable token in GET

To prevent adding `token` on GET:

```env
VITE_INCLUDE_TOKEN_IN_GET=false
```

---

## 🪄 Examples of Integration

### React (Vite)

```ts
import post, { get } from "@sfutureapps/req-sdk";

export async function useLogin() {
  const res = await post({
    endpoint: "/auth/login",
    data: { username: "john", password: "1234" },
  });
  console.log(res);
}
```

### Next.js (Client Component)

```tsx
"use client";
import { useEffect } from "react";
import post from "@sfutureapps/req-sdk";

export default function Page() {
  useEffect(() => {
    post({ endpoint: "/ping" }).then(console.log);
  }, []);
  return <div>Loading...</div>;
}
```

---

## 🧩 Supported Environments

✅ Node.js ≥ 18  
✅ Vite ≥ 4  
✅ React ≥ 18  
✅ Next.js ≥ 13 (App Router)  
✅ TypeScript ≥ 5

---

## 🧑‍💻 Contributing

Pull requests are welcome!  
If you find a bug or want to add a feature:

1. Fork the repo
2. Create your feature branch
3. Commit your changes
4. Run `npm test` (coming soon)
5. Open a pull request 🎉

---

## 🪪 License

MIT License © 2025 [sFutureApps](https://sfutureapps.com)

---

## ❤️ Credits

Developed by **KHUT Lihong** (CEO, sFutureApps)  
Email: support@sfutureapps.com  
Website: [https://sfutureapps.com](https://sfutureapps.com)