# DJUST Front SDK

> **Universal TypeScript SDK for DJUST B2B API**  
> SSR-safe, type-safe, production-ready.

[![npm version](https://img.shields.io/npm/v/@djust-b2b/djust-front-sdk)](https://www.npmjs.com/package/@djust-b2b/djust-front-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue.svg)](https://www.typescriptlang.org/)

**DJUST Front SDK** is a comprehensive JavaScript/TypeScript development kit designed to simplify and optimize API calls to the DJUST backend. It offers a secure, high-performance, and ready-to-use solution for integration partners, facilitating the implementation of robust B2B e-commerce solutions.

---

## ✨ Features

### 🔒 **Security First**
- Secure token management with HTTP-only cookies support
- SSR-safe architecture prevents state leakage
- Built-in authentication lifecycle hooks
- Comprehensive error handling with typed exceptions

### ⚡ **Performance Optimized**
- **Request deduplication** - Automatic duplicate request prevention
- **Response caching** - Configurable TTL with stale-while-revalidate
- **Request batching** - Automatic batching of parallel requests
- **Performance monitoring** - Built-in metrics and monitoring

### 🎯 **Type-Safe**
- Full TypeScript support with strict typing
- Auto-completion in IDEs
- Request/Response interfaces for all operations
- Type guards and runtime validation

### 🧩 **Universal Compatibility**
- Works in **Node.js**, **Browser**, and **SSR** environments
- Compatible with **Vue.js**, **React**, **Nuxt**, **Next.js**, **Angular**
- Framework-agnostic design
- Tree-shakeable modules

### 🔧 **Developer Experience**
- Modular service architecture
- Comprehensive documentation
- Extensive examples and guides
- Production-ready error handling

---

## 📦 Installation

```bash
# Stable v3 (npm tag: latest)
npm install @djust-b2b/djust-front-sdk@latest

# Maintenance v2 (npm tag: v2) — legacy portails
npm install @djust-b2b/djust-front-sdk@v2
```

| npm tag | Version | Use when |
|---------|---------|----------|
| `latest` | 3.0.0+ | New projects, SSR with `createDjustClient` (published from `preprod`) |
| `v2` | 2.19.1 | Legacy portails not yet migrated |
| `beta` | 3.0.0-beta.* | RC validation (`beta` branch) |

**Legacy imports:** paths like `@djust-b2b/djust-front-sdk/lib/interfaces/models/product` remain valid on v3.

```bash
# yarn / pnpm
yarn add @djust-b2b/djust-front-sdk
pnpm add @djust-b2b/djust-front-sdk
```

---

## 🚀 Quick Start

### Basic Usage

```typescript
import { createDjustClient } from '@djust-b2b/djust-front-sdk';

// Create client instance
const client = createDjustClient({
  baseUrl: 'https://api.djust.io',
  clientId: 'your-client-id',
  apiKey: 'your-api-key',
  locale: 'fr-FR',
  storeId: 'store-123',
  storeViewId: 'view-456',
});

// Create scoped client with authentication
const sdk = client.withContext({
  accessToken: 'your-access-token',
  customerAccountId: 'account-123',
});

// Use the SDK
const cart = await sdk.getCart({
  cartId: 'cart-123',
  currency: 'EUR',
});

const products = await sdk.getProductsList({
  locale: 'fr-FR',
  pageable: { page: 0, size: 20 },
});
```

### SSR Usage (Nuxt/Next.js)

```typescript
// server/api/cart.get.ts (Nuxt)
import { useDjustSDK } from '~/server/utils/djust-sdk';

export default defineEventHandler(async (event) => {
  const sdk = useDjustSDK(event); // Automatically reads cookies
  
  const cart = await sdk.getCart({
    cartId: 'cart-123',
    currency: 'EUR',
  });
  
  return cart;
});
```

### Client-Side Usage

```typescript
// app/composables/useCart.ts (Nuxt)
import { createDjustClient } from '@djust-b2b/djust-front-sdk';

export const useCart = () => {
  const { $config } = useNuxtApp();
  const { token } = useAuth(); // Your auth composable
  
  const client = createDjustClient({
    baseUrl: $config.public.apiBaseUrl,
    clientId: $config.public.apiClientId,
    apiKey: $config.public.apiKey,
  });
  
  const sdk = client.withContext({
    accessToken: token.value,
  });
  
  return {
    getCart: (cartId: string) => sdk.getCart({ cartId, currency: 'EUR' }),
    updateCart: (params: UpdateCartParams) => sdk.updateCart(params),
  };
};
```

---

## 📚 Documentation

### For Users

- **[Getting Started](./docs/getting-started/introduction.mdx)** — setup guide (Mintlify site in [`docs/`](./docs/))
- **[API Reference](./docs/api-reference/overview.mdx)** — typed client methods per service
- **[Error Handling](./docs/guides/error-handling.mdx)** — `SDKError` hierarchy and retries
- **[Versioning](./docs/guides/versioning.mdx)** — npm tags and release policy
- **[Guides](./docs/guides/)** — SSR, sessions, performance, MCP, and more

Run locally: `cd docs && npm install && npx mint dev` (Node 20–22). Deployed via the Mintlify GitLab app.

### For Developers

- **[CLAUDE.md](./CLAUDE.md)** — repo layout, golden rule, service anatomy, conventions
- **[ARCHITECTURE_AUDIT.md](./ARCHITECTURE_AUDIT.md)** — staff engineer architecture audit
- **[docs/README.md](./docs/README.md)** — regenerate and validate the Mintlify site

### Quick Links

| Topic | Link |
|-------|------|
| Architecture | [Overview](./docs/overview/architecture.mdx) |
| Services | [Services guide](./docs/guides/services.mdx) |
| SSR | [SSR usage](./docs/guides/ssr-usage.mdx) |
| Error Handling | [Error handling](./docs/guides/error-handling.mdx) |
| API playground | [OpenAPI](./docs/openapi.json) (interactive on deployed site) |

---

## 🎯 Key Features in Detail

### SSR-Safe Architecture

The SDK uses request-scoped instances to prevent state leakage in SSR environments:

```typescript
// Each request gets its own scoped client
const sdk = client.withContext({
  accessToken: getCookie(event, 'token'),
  customerAccountId: getCookie(event, 'customer-account-id'),
  requestId: `ssr-${Date.now()}`,
});
```

### Performance Optimizations

Enable performance features in client configuration:

```typescript
const client = createDjustClient({
  // ... base config
  performance: {
    deduplication: true,      // Prevent duplicate requests
    cache: true,              // Enable response caching
    cacheTTL: 30000,          // 30 seconds TTL
    staleWhileRevalidate: true, // Serve stale while revalidating
    compression: true,         // Enable compression
    keepAlive: true,          // HTTP keep-alive
  },
});
```

### Error Handling

Structured error model with typed exceptions and rich metadata:

```typescript
import {
  ValidationError,
  NotFoundError,
  ForbiddenError,
  SDKError,
} from '@djust-b2b/djust-front-sdk';

try {
  const cart = await sdk.getCart({ cartId: 'invalid' });
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Invalid parameters:', error.message);
    // Access metadata for debugging
    console.log('Backend endpoint:', error.metadata.endpoint);
    console.log('SDK method:', error.metadata.sdkMethod);
    console.log('Query params:', error.metadata.queryParams);
  } else if (error instanceof NotFoundError) {
    console.error('Cart not found');
  } else if (error instanceof ForbiddenError) {
    console.error('Access denied');
  }
}
```

**SSR/BFF Integration**: Use centralized error handler for Nuxt/Next.js:

```typescript
import { handleSDKError } from '~~/server/utils/handle-sdk-error';

export default defineEventHandler(async (event) => {
  try {
    const sdk = event.context.djustSDK();
    return await sdk.updateCommercialOrderLines({ ... });
  } catch (error) {
    const errorResponse = await handleSDKError(error, event);
    if (errorResponse) return errorResponse;
    throw createError({ statusCode: 500, ... });
  }
});
```

See [Error Handling Guide](https://djust-sdk-docs-530629704769.europe-west1.run.app/docs/guides/error-handling) for complete documentation.

### Authentication Hooks

Subscribe to authentication lifecycle events:

```typescript
const client = createDjustClient({
  // ... config
  authHooks: {
    onLogin: async (ctx) => {
      console.log('User logged in:', ctx.userId);
      // Update your app state
    },
    onTokenRefresh: async (ctx) => {
      console.log('Token refreshed:', ctx.requestId);
      // Update token in your store
    },
    onLogout: async () => {
      console.log('User logged out');
      // Clear app state
    },
    onAuthFailure: async (ctx) => {
      console.error('Auth failed:', ctx.endpoint);
      // Handle auth failure
    },
  },
});
```

---

## 🏗️ Architecture

The SDK follows a modular, service-based architecture:

```
┌─────────────────────────────────────┐
│      createDjustClient()            │
│      (Client Factory)               │
└──────────────┬──────────────────────┘
               │
    ┌──────────┴──────────┐
    │                     │
┌───▼──────┐      ┌───────▼────────┐
│ Transport│      │ Service Factory│
│ (HTTP)   │      │ (Registry)    │
└───┬──────┘      └───────┬────────┘
    │                     │
    └──────────┬──────────┘
               │
    ┌──────────▼──────────┐
    │   Services         │
    │  (Auth, Cart,      │
    │   Product, etc.)   │
    └────────────────────┘
```

### Available Services

- **Auth** - Authentication and user management
- **Cart** - Shopping cart operations
- **Product** - Product catalog and search
- **Commercial Order** - Order management
- **Logistic Order** - Shipping and logistics
- **Quote** - B2B quote management
- **Customer Account** - Account management
- **Customer User** - User profile management
- **Supplier** - Supplier information
- **Payment** - Payment processing
- **Navigation** - Category navigation
- And more...

See [Services Reference](./docs/guides/services.mdx) for complete list.

---

## 🔧 Configuration

### Client Configuration

```typescript
interface DjustClientConfig {
  baseUrl: string;              // DJUST API base URL
  clientId: string;              // Client ID (dj-client header)
  apiKey: string;               // API Key (dj-api-key header)
  timeout?: number;              // Request timeout (default: 30000)
  locale?: string;               // Default locale
  storeId?: string;             // Default store ID
  storeViewId?: string;          // Default store view ID
  strictErrors?: boolean;        // Use SDKError (default: false)
  retry?: RetryConfig;           // Retry configuration
  performance?: PerformanceConfig; // Performance options
  authHooks?: AuthHooks;         // Authentication hooks
  debug?: boolean;               // Debug mode
}
```

### Performance Configuration

```typescript
interface PerformanceConfig {
  deduplication?: boolean;      // Request deduplication
  cache?: boolean;              // Response caching
  cacheTTL?: number;            // Cache TTL in ms
  staleWhileRevalidate?: boolean; // SWR strategy
  compression?: boolean;        // Enable compression
  keepAlive?: boolean;          // HTTP keep-alive
}
```

### Retry Configuration

```typescript
interface RetryConfig {
  enabled?: boolean;            // Enable retries
  maxAttempts?: number;         // Max retry attempts
  retryableStatuses?: number[]; // Status codes to retry
}
```

---

## 📖 Examples

### Authentication

```typescript
// Login
const { token, refreshToken, user } = await sdk.login({
  username: 'user@example.com',
  password: 'password',
  withUser: true,
});

// Refresh token
const newToken = await sdk.refreshToken({
  refreshToken: refreshToken,
});

// Get authenticated user
const user = await sdk.getAuthenticatedUser();
```

### Shopping Cart

```typescript
// Get cart
const cart = await sdk.getCart({
  cartId: 'cart-123',
  currency: 'EUR',
  nbFirstLines: 10,
});

// Update cart lines
await sdk.updateCartLines({
  cartId: 'cart-123',
  linesToAdd: [
    { offerPriceId: 'price-1', quantity: 5 },
  ],
  linesToUpdate: [
    { lineId: 'line-1', quantity: 10 },
  ],
});

// Convert to order
const order = await sdk.initializeOrders({
  cartId: 'cart-123',
  shippingAddressId: 'addr-123',
});
```

### Products

```typescript
// Search products
const results = await sdk.getProductsList({
  locale: 'fr-FR',
  filters: { categoryId: 'cat-123' },
  pageable: { page: 0, size: 20 },
});

// Get product details
const product = await sdk.getProduct({
  productIdentifier: 'SKU-123',
  productIdType: 'SKU',
  locale: 'fr-FR',
});

// Get product offers
const offers = await sdk.getProductPaginatedOffers({
  productVariantId: 'variant-123',
  pageable: { page: 0, size: 20 },
});
```

### Orders

```typescript
// Get orders
const orders = await sdk.getCommercialOrders({
  locale: 'fr-FR',
  pageable: { page: 0, size: 10 },
});

// Get order details
const order = await sdk.getCommercialOrder({
  commercialOrderId: 'order-123',
  locale: 'fr-FR',
});

// Create order from cart
const newOrder = await sdk.createCommercialOrder({
  channel: 'DESKTOP',
  locale: 'fr-FR',
  origin: 'CART',
  originId: 'cart-123',
});
```

---

## 🛡️ Security Best Practices

### Token Management

```typescript
// ✅ Good - Use HTTP-only cookies in SSR
// Server-side
setCookie(event, 'token', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
});

// ✅ Good - Don't log tokens
// Never do this:
console.log('Token:', token); // ❌

// ✅ Good - Validate tokens
if (!isValidToken(token)) {
  throw new Error('Invalid token');
}
```

### Input Validation

```typescript
// ✅ Good - Validate before sending
async getCart(params: GetCartParams) {
  this.required(params, ['cartId', 'currency']);
  
  // Additional validation
  if (!/^[a-zA-Z0-9-]+$/.test(params.cartId)) {
    throw ValidationError.invalidParameter('cartId');
  }
  
  return this.request(...);
}
```

---

## 🧪 Testing

The SDK includes comprehensive test coverage:

```bash
# Run tests
npm test

# Run tests in watch mode
npm run test:ui

# Run tests with coverage
npm run coverage
```

---

## 📊 Performance Monitoring

Access performance metrics:

```typescript
const metrics = client.getMetrics();

console.log('Total requests:', metrics.totalRequests);
console.log('Cache hits:', metrics.cacheHits);
console.log('Cache misses:', metrics.cacheMisses);
console.log('Average response time:', metrics.avgResponseTime);
```


---

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](./CONTRIBUTING.md) for details.

### Quick Start for Contributors

1. Fork the repository
2. Create a feature branch: `git checkout -b feat/your-feature`
3. Make your changes following [CLAUDE.md](./CLAUDE.md) conventions
4. Write tests for your changes
5. Commit using conventional commits: `npm run commit`
6. Push and create a Merge Request

### Development Setup

```bash
# Clone repository
git clone https://gitlab.com/djustlab/front/djust-front-sdk.git
cd djust-front-sdk

# Install dependencies
npm install

# Run tests
npm test

# Build
npm run build

# Format code
npm run format

# Lint
npm run lint
```

---

## 📝 Changelog

See [CHANGELOG.md](./CHANGELOG.md) for a detailed list of changes.

## 🔄 Versioning

The SDK follows [Semantic Versioning](https://semver.org/). Check versions:

```bash
# View all versions
npm view @djust-b2b/djust-front-sdk versions

# View latest version
npm view @djust-b2b/djust-front-sdk version

# Check installed version
npm list @djust-b2b/djust-front-sdk
```

See [Versioning Guide](https://djust-sdk-docs-530629704769.europe-west1.run.app/docs/guides/versioning) for complete documentation on version management and npm version retrieval.

---

## 🐛 Reporting Issues

Found a bug or have a feature request? Please open an issue on [GitLab Issues](https://gitlab.com/djustlab/front/djust-front-sdk/issues).

---

## 📄 License

DJUST Front SDK is distributed under the **MIT License**. See [LICENSE](./LICENSE) for details.

---

## 🔗 Links

- **Documentation**: [https://djust-sdk-docs-530629704769.europe-west1.run.app](https://djust-sdk-docs-530629704769.europe-west1.run.app)
- **GitLab Repository**: [https://gitlab.com/djustlab/front/djust-front-sdk](https://gitlab.com/djustlab/front/djust-front-sdk)
- **Issues**: [https://gitlab.com/djustlab/front/djust-front-sdk/issues](https://gitlab.com/djustlab/front/djust-front-sdk/issues)

---

## 💬 Support

- **Documentation**: Check our [documentation site](https://djust-sdk-docs-530629704769.europe-west1.run.app)
- **Issues**: Open an issue on [GitLab](https://gitlab.com/djustlab/front/djust-front-sdk/issues)
- **Team Chat**: Contact the development team

---

**Built with ❤️ by the DJUST team**

With **DJUST Front SDK**, simplify your backend integrations, ensure exceptional performance, and provide reliable and secure e-commerce solutions for your clients.
