# 🔌 Nucleus Generic API Caller

> **Internal package for [Nucleus](https://github.com/risewithus/Nucleus) project.**
> This package is published for internal use and is not accepting external contributions.

Type-safe API caller for Next.js Server Actions with automatic CRUD endpoint generation from database schemas.

## Overview

- Server-side API factory with automatic token refresh and cookie handling
- Generic CRUD endpoints generated from schema definitions
- Type-safe React hooks for API calls
- Built on [@hidayetcanozcan/custom-fetch](https://www.npmjs.com/package/@hidayetcanozcan/custom-fetch)

## Installation

```bash
bun add @hidayetcanozcan/nucleus-generic-api-caller @hidayetcanozcan/custom-fetch
```

## Nucleus Project Setup

### 1. Create Config File

```typescript
// lib/api/config.ts
import type { NucleusApiConfig } from "@hidayetcanozcan/nucleus-generic-api-caller";
import { generateGenericEndpoints } from "@hidayetcanozcan/nucleus-generic-api-caller";
import * as AllSchemas from "@monorepo/db-entities/schemas";
import { customSettings } from "./custom-settings";
import { vorionSettings } from "./vorion";

const { endpoints: genericEndpoints, settings: genericSettings } = generateGenericEndpoints(AllSchemas);

export const Endpoints = {
  ...genericEndpoints,
  ...CustomEndpoints,
  ...VorionEndpoints,
};

export const apiConfig: NucleusApiConfig = {
  baseUrl: process.env.AUTH_API_URL!,
  alternateBaseUrl: process.env.VORION_API_URL,
  shouldUseAlternateUrl: (endpoint) => endpoint.startsWith("Vorion: "),
  settings: {
    ...genericSettings,
    ...customSettings,
    ...vorionSettings,
  },
  authCookieName: "nucleus_access_token",
  refreshCookieName: "nucleus_refresh_token",
  refreshEndpoint: "/v2/auth/refresh",
  refreshExcludedEndpoints: ["Login", "Login V2", "Register V2", "Refresh V2", "Logout V2"],
  authCreationEndpoints: ["Login", "Login V2", "Register V2"],
  cookieSettingEndpoints: ["Login", "Login V2", "Register V2"],
  logoutEndpoint: "Logout",
  enableBypassHeader: process.env.BYPASS_IDENTITY_MIDDLEWARE === "true",
  debug: process.env.NODE_ENV === "development",
};
```

### 2. Create Factory (Server Action)

```typescript
// lib/api/factory.ts
"use server";

import { cookies, headers } from "next/headers";
import { CustomFetch } from "@hidayetcanozcan/custom-fetch";
import { createNucleusApiFactory } from "@hidayetcanozcan/nucleus-generic-api-caller/server";
import { apiConfig, Endpoints } from "./config";

const NucleusApi = createNucleusApiFactory(apiConfig);

export async function FactoryFunction<Payload, Success, Error>(
  payload: Payload,
  endpoint: string,
) {
  const cookieStore = await cookies();
  const headersList = await headers();

  return NucleusApi<Payload, Success, Error>(payload, endpoint, {
    cookies: {
      get: (name) => cookieStore.get(name),
      set: (name, value, opts) => cookieStore.set(name, value, opts),
      delete: (name) => cookieStore.delete(name),
    },
    headers: {
      get: (name) => headersList.get(name),
      forEach: (cb) => headersList.forEach(cb),
    },
  });
}

export async function Factory({ endpoint }: { endpoint: string }) {
  return (payload: unknown, ep: string) => FactoryFunction(payload, ep);
}

export { Endpoints };
```

### 3. Create Hook (Client)

```typescript
// lib/api/hook.ts
"use client";

import { createNucleusApiHook } from "@hidayetcanozcan/nucleus-generic-api-caller/client";
import * as AllSchemas from "@monorepo/db-entities/schemas";
import { Endpoints, Factory } from "./factory";
import { CustomEndpoints } from "./custom-endpoints";
import type { ActionTypes } from "./types";

export const useGenericApiActions = createNucleusApiHook<typeof Endpoints, ActionTypes>({
  endpoints: Endpoints,
  customEndpoints: CustomEndpoints,
  schemas: AllSchemas,
  factory: async (endpoint) => Factory({ endpoint }),
  routerPush: (path) => {
    if (typeof window !== "undefined") window.location.href = path;
  },
});
```

### 4. Usage in Components

```tsx
"use client";

import { useGenericApiActions } from "@/lib/api/hook";

export function UserList() {
  const actions = useGenericApiActions();

  const loadUsers = () => {
    actions.GET_USERS?.start({
      payload: { page: 1, limit: 10 },
      onAfterHandle: (data) => console.log("Users:", data),
      onErrorHandle: (error) => console.error("Error:", error),
    });
  };

  return (
    <div>
      <button onClick={loadUsers} disabled={actions.GET_USERS?.state?.isPending}>
        {actions.GET_USERS?.state?.isPending ? "Loading..." : "Load Users"}
      </button>
    </div>
  );
}
```

## API Reference

| Export | Description |
|--------|-------------|
| `createNucleusApiFactory` | Server-side API factory |
| `createNucleusApiHook` | Client-side React hook |
| `generateGenericEndpoints` | CRUD generator from schemas |
| `GenericMethods` | Enum: GET, CREATE, UPDATE, DELETE, TOGGLE, VERIFICATION |

## License

MIT - Internal use only.
