npm package: @irmscheremilio/mockend
Description: AI-powered frontend-first development toolkit - Build frontends without waiting for backends
Latest version: 1.3.8
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Mockend SDK

AI-powered frontend-first development toolkit. Build your frontend without waiting for a backend.

## Features

- **Zero Backend Dependency**: Develop frontend-first with automatic mock data generation
- **AI-Powered Mocks**: Realistic data generated by OpenAI with intelligent caching
- **Faker.js Mode**: Offline mode for CI/CD pipelines - no AI dependency required
- **Schema-Based Type System**: Zod-like schema builder for single source of truth
- **Type-Safe**: Full TypeScript support with automatic type inference
- **Seamless Production Switch**: One config change to switch from mocks to real backend
- **Smart Caching**: In-memory, localStorage, or file-based caching strategies
- **Performance Optimized**: <10ms mock generation after first AI cache
- **OpenAPI Generation**: Auto-generate API specs for backend developers
- **CI/CD Ready**: Deterministic Faker.js mode with seed support for testing

## Installation

```bash
npm install @irmscheremilio/mockend
```

## Quick Start

```typescript
import { defineMockEndpoint, configureMockend, m, type Infer } from "@irmscheremilio/mockend";

// Configure Mockend
// Get your free API key and project ID at https://platform.mockend.io
configureMockend({
  mockendApiKey: process.env.MOCKEND_API_KEY,
  projectId: process.env.MOCKEND_PROJECT_ID, // Required for API requests
  backendBaseUrl: "https://api.myapp.com", // For production
  environment: process.env.NODE_ENV === "production" ? "production" : "development",
  cacheEnabled: true,
  persistentCache: true, // Enable localStorage persistence in browser
});

// Define schema
const UserSchema = m.object({
  id: m.uuid(),
  name: m.person.fullName(),
  email: m.email(),
});

// Infer TypeScript type
type User = Infer<typeof UserSchema>;

// Define endpoint
export const getUsers = defineMockEndpoint<User[]>({
  path: "/api/users",
  method: "GET",
  schema: UserSchema,
  mock: {
    count: 5,
  },
});

// Use it
const users = await getUsers();
console.log(users); // Fully typed as User[]
```

## Configuration

Get your free API key and project ID at [https://platform.mockend.io](https://platform.mockend.io)

```typescript
configureMockend({
  mockendApiKey: string,         // Mockend Platform API key (mk_live_xxx) - required for AI generation
  projectId: string,             // Project ID for multi-project isolation - required
  backendBaseUrl: string,        // Real backend URL for production
  environment: "development" | "production",
  cacheEnabled: boolean,         // Enable/disable caching (default: true)
  persistentCache: boolean,      // Enable localStorage persistence in browser (default: false)
  generateMode: "ai" | "faker" | "auto",  // Generation mode (default: "auto")
  fakerSeed: number,             // Seed for deterministic Faker.js generation (optional)
  regenerateOnConfigChange: boolean,  // Regenerate when endpoint config changes (default: true)
});
```

## Generation Modes

Mockend supports three generation modes to fit different development scenarios:

### AI Mode (Realistic Data)
Best for development and prototyping with realistic, contextual data.

```typescript
configureMockend({
  mockendApiKey: "mk_live_xxx",
  generateMode: "ai", // Always use AI - requires API key
});
```

**Use cases:**
- Frontend development with realistic data
- UI/UX prototyping
- Demos and presentations

### Faker Mode (CI/CD & Offline)
Pure Faker.js generation without network dependency. Perfect for CI/CD pipelines.

```typescript
configureMockend({
  mockendApiKey: "mk_live_xxx", // Required (free tier = unlimited Faker)
  generateMode: "faker",
  fakerSeed: 12345,             // Optional: deterministic data for tests
});
```

**Use cases:**
- CI/CD pipelines (Jenkins, GitHub Actions)
- Integration tests
- Offline development (after initial API key setup)
- Air-gapped environments

**Benefits:**
- ✅ No network calls during generation
- ✅ **Unlimited on free tier**
- ✅ Fast generation (<1ms)
- ✅ Deterministic with seed (reproducible tests)

**Note:** API key required for all modes (including Faker) for user tracking and quota management. Free tier includes unlimited Faker.js mode.

### Auto Mode (Default - Best of Both)
Tries AI first, falls back to Faker.js if API key is missing or network fails.

```typescript
configureMockend({
  mockendApiKey: "mk_live_xxx", // Optional
  generateMode: "auto", // Default mode
});
```

**Use cases:**
- Teams with mixed workflows
- Gradual adoption
- Offline-first development

## CI/CD Example

Use Faker mode in your test pipeline for fast, deterministic mocks:

```typescript
// jest.setup.ts or vitest.config.ts
import { configureMockend } from "@irmscheremilio/mockend";

configureMockend({
  mockendApiKey: process.env.MOCKEND_API_KEY, // Required (use free tier)
  generateMode: "faker",                       // No network calls
  fakerSeed: 12345,                            // Same data every test run
  environment: "development",
  cacheEnabled: true,
});
```

```yaml
# .github/workflows/test.yml
- name: Run tests
  run: npm test
  env:
    NODE_ENV: development
    MOCKEND_API_KEY: ${{ secrets.MOCKEND_API_KEY }} # Free tier = unlimited Faker
```

**Why API key is required:**
- ✅ User tracking (helps us improve the product)
- ✅ Quota management (prevents abuse)
- ✅ **Free tier includes unlimited Faker.js mode** - perfect for CI/CD
- ✅ No network calls are made in Faker mode (offline-safe)

### Getting Started

1. Sign up for a free account at [https://platform.mockend.io](https://platform.mockend.io)
2. Create an API key from your dashboard
3. Add the API key to your environment variables:
   ```bash
   MOCKEND_API_KEY=mk_live_your_api_key_here
   ```
4. Configure Mockend in your app (see Quick Start above)

## Schema Builder (`m`)

### Basic Types

```typescript
const schema = m.object({
  id: m.uuid(),
  text: m.string(),
  count: m.number(),
  active: m.boolean(),
  createdAt: m.date(),
  email: m.email(),
  website: m.url(),
  phone: m.phoneNumber(),
});
```

### Person Fields

```typescript
const person = m.object({
  fullName: m.person.fullName(),
  firstName: m.person.firstName(),
  lastName: m.person.lastName(),
  jobTitle: m.person.jobTitle(),
});
```

### Internet Fields

```typescript
const profile = m.object({
  userName: m.internet.userName(),
  avatar: m.internet.avatar(),
});
```

### Location Fields

```typescript
const address = m.object({
  street: m.location.street(),
  city: m.location.city(),
  state: m.location.state(),
  zipCode: m.location.zipCode(),
  country: m.location.country(),
  latitude: m.location.latitude(),
  longitude: m.location.longitude(),
});
```

### Commerce Fields

```typescript
const product = m.object({
  name: m.commerce.productName(),
  department: m.commerce.department(),
  price: m.commerce.price(),
});
```

### Lorem Fields

```typescript
const content = m.object({
  word: m.lorem.word(),
  sentence: m.lorem.sentence(),
  paragraph: m.lorem.paragraph(),
});
```

### Nested Objects

```typescript
const user = m.object({
  id: m.uuid(),
  name: m.person.fullName(),
  address: m.object({
    street: m.location.street(),
    city: m.location.city(),
  }),
});
```

### Arrays

```typescript
const article = m.object({
  id: m.uuid(),
  title: m.lorem.sentence(),
  tags: m.array(m.lorem.word()),
});
```

## Type Inference

Use `Infer<>` to extract TypeScript types from schemas:

```typescript
const ProductSchema = m.object({
  id: m.uuid(),
  name: m.commerce.productName(),
  price: m.commerce.price(),
});

type Product = Infer<typeof ProductSchema>;
// { id: string; name: string; price: number }
```

## Mock Configuration

```typescript
mock: {
  count: 10, // Generate array of 10 items
  instruction: "Generate premium users with verified accounts", // Optional AI instruction
  delay: 500, // Simulate loading delay in milliseconds (only for cached data)
}
```

### Simulating Network Latency

The `delay` option allows you to simulate realistic network latency for cached mock data. This is useful for:
- Testing loading states and spinners
- Simulating slow network conditions
- Demonstrating progressive loading UIs
- E2E tests that expect async behavior

```typescript
export const getUsers = defineMockEndpoint<User[]>({
  path: "/api/users",
  method: "GET",
  schema: UserSchema,
  mock: {
    count: 5,
    delay: 800, // Simulate 800ms network latency
  },
});

// Usage - will wait 800ms before returning cached data
const users = await getUsers(); // Takes ~800ms when cache hit
```

**Important Notes:**
- Delay only applies to **cached data** (cache hits)
- First request (cache miss) uses actual AI/Faker generation time
- Set `delay: 0` or omit it for instant responses
- Useful for testing loading states without slowing down development

## Caching Strategies

### Browser (default)
In-memory cache (clears on page reload):
```typescript
configureMockend({ cacheEnabled: true });
```

### Browser (persistent)
localStorage cache (persists across reloads):
```typescript
configureMockend({
  cacheEnabled: true,
  persistentCache: true,
});
```

### Node.js
File-based cache (`.mockend-cache.json`) - automatic

### Cache Invalidation on Config Changes

By default, Mockend regenerates mock data when your endpoint configuration changes (e.g., changing the HTTP method, mock count, or mock instruction). This ensures your mocked data always matches your current configuration.

```typescript
// Default behavior - cache invalidates when config changes
configureMockend({
  regenerateOnConfigChange: true, // default
});

// Example: Changing the endpoint config will trigger regeneration
export const getUsers = defineMockEndpoint<User[]>({
  path: "/api/users",
  method: "GET", // If you change this to "POST", cache invalidates
  schema: UserSchema,
  mock: {
    count: 5, // If you change this to 10, cache invalidates
    instruction: "Generate users from tech companies", // Changing this invalidates cache
  },
});
```

**Disable config-based invalidation:**
```typescript
// Cache only invalidates on schema changes, not config changes
configureMockend({
  regenerateOnConfigChange: false,
});
```

**What triggers cache invalidation:**
- When `regenerateOnConfigChange: true` (default):
  - Schema structure changes
  - HTTP method changes
  - Mock count changes
  - Mock instruction changes
  - Mock delay changes
  - Generate mode changes
  - Request params changes

- When `regenerateOnConfigChange: false`:
  - Only schema structure changes
  - Request params changes

**Use cases:**
- `regenerateOnConfigChange: true` - Recommended for most development scenarios
- `regenerateOnConfigChange: false` - Use when you want stable mock data even when tweaking endpoint config

## CLI Commands

### Generate OpenAPI Spec

Generate an OpenAPI 3.0 specification from your defined Mockend endpoints:

```bash
# Basic usage - generates openapi.json
npx mockend openapi

# Specify output file
npx mockend openapi -o api-spec.json

# Full customization
npx mockend openapi \
  -o ./docs/api.json \
  -t "My API" \
  -v "2.0.0" \
  -d "API for My Application" \
  -s https://api.example.com
```

**Options:**
- `-o, --output <path>` - Output file path (default: `./openapi.json`)
- `-t, --title <title>` - API title (default: `Mockend Generated API`)
- `-v, --version <version>` - API version (default: `1.0.0`)
- `-d, --description <description>` - API description
- `-s, --server <url>` - Server URL (e.g., `https://api.example.com`)

The generated spec includes:
- Request/response schemas from your Mockend schemas
- Path parameters (e.g., `:id`)
- Request bodies for POST/PUT/PATCH
- Tags for organization
- Error responses (400, 404, 500)

### Regenerate Mock Data

Clear cached mock data to regenerate fresh data:

```bash
# Clear all cache
npx mockend regenerate

# Preview what's cached (without clearing)
npx mockend regenerate --preview

# Clear specific cache entry by hash
npx mockend regenerate --hash abc123xyz

# Clear entries matching a pattern
npx mockend regenerate --endpoint users
```

**Options:**
- `--preview, -p` - Show cached endpoints without clearing
- `--hash <hash>, -h` - Clear cache for specific hash
- `--endpoint <pattern>, -e` - Clear cache entries matching pattern

**Example output (preview mode):**
```
📋 Cached Endpoints:

  [1] Hash: abc123xyz
      Cached: 12/21/2025, 3:45 PM
      Preview: {"id":"550e8400-e29b-41d4-a716-446655440000","name":"John Doe","email":"john@example.com"}...

  [2] Hash: def456uvw
      Cached: 12/21/2025, 3:47 PM
      Preview: [{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","title":"Product A","price":49.99}...

  Total: 2 cached endpoint(s)

💡 Tip: Run 'npx mockend regenerate' to clear all cache
        Run 'npx mockend regenerate --hash <hash>' to clear specific entry
```

### Inspect Cache

Inspect what's currently cached to understand your mock data state:

```bash
# List all cached entries
npx mockend cache

# Show full data for a specific hash
npx mockend cache --hash abc123xyz

# Search for entries matching a pattern
npx mockend cache --search users

# Search with full data output
npx mockend cache --search products --full
```

**Options:**
- `--list, -l` - List all cached entries (default behavior)
- `--hash <hash>, -h` - Show full details for a specific cache entry
- `--search <pattern>, -s` - Search for entries matching pattern
- `--full, -f` - Show full data instead of preview (use with `--search`)

**Example output (list all):**
```
📋 Cached Endpoints (3 total):

  [1] Hash: abc123xyz
      Cached: 12/21/2025, 3:45 PM
      Preview: {"id":"550e8400-e29b-41d4-a716-446655440000","name":"John Doe","email":"john@example.com"}...

  [2] Hash: def456uvw
      Cached: 12/21/2025, 3:47 PM
      Preview: [{"id":"7c9e6679-7425-40de-944b-e07fc1f90ae7","title":"Product A","price":49.99}...

  [3] Hash: ghi789rst
      Cached: 12/21/2025, 4:12 PM
      Preview: {"userId":"9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d","orderId":"a1b2c3d4","total":199.99}...

💡 Tips:
   - Use 'npx mockend cache --hash <hash>' to see full data
   - Use 'npx mockend cache --search <pattern>' to filter entries
   - Use 'npx mockend regenerate --hash <hash>' to clear specific entry
```

**Example output (specific hash):**
```
📦 Cache Entry: abc123xyz
   Cached: 12/21/2025, 3:45 PM
   Schema Hash: abc123xyz

   Data:
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "John Doe",
  "email": "john@example.com",
  "createdAt": "2025-12-20T15:30:00.000Z"
}
```

### Clear Cache

Clear the Mockend cache file (legacy command - use `regenerate` instead):

```bash
npx mockend clear-cache
```

## Environment Switching

Development (uses mocks):
```bash
NODE_ENV=development npm run dev
```

Production (uses real backend):
```bash
NODE_ENV=production npm run build
```

## Advanced Example

```typescript
const ProductSchema = m.object({
  id: m.uuid(),
  name: m.commerce.productName(),
  price: m.commerce.price(),
  inStock: m.boolean(),
  category: m.object({
    id: m.uuid(),
    name: m.commerce.department(),
  }),
  reviews: m.array(m.object({
    id: m.uuid(),
    rating: m.number(),
    comment: m.lorem.paragraph(),
  })),
});

type Product = Infer<typeof ProductSchema>;

export const getProducts = defineMockEndpoint<Product[]>({
  path: "/api/products",
  method: "GET",
  schema: ProductSchema,
  mock: {
    count: 10,
    instruction: "Generate realistic e-commerce products",
  },
});

export const getProduct = defineMockEndpoint<Product>({
  path: "/api/products/:id",
  method: "GET",
  schema: ProductSchema,
  mock: {},
});

// Usage with dynamic routes
const product = await getProduct({ id: "123" });
```

## Dynamic Parameters & Variable Interpolation

Mockend supports dynamic parameters that can be used in both API calls and AI instructions. This enables context-aware mock data generation based on runtime values.

### Template Syntax

Use `{{variable}}` syntax in your instruction to interpolate parameter values:

```typescript
export const filterOffers = defineMockEndpoint<Offer[]>({
  method: "GET",
  path: "/api/v1/offers",
  schema: OfferSchema,
  mock: {
    count: 20,
    instruction: "Generate {{filter}} offers for companies in the {{sector}} sector"
  }
});

// Usage - variables are interpolated into the instruction
const offers = await filterOffers({
  filter: "outgoing",
  sector: "construction"
});
// Instruction becomes: "Generate outgoing offers for companies in the construction sector"
```

### Use Cases

**1. Filtering & Search**

```typescript
export const searchProducts = defineMockEndpoint<Product[]>({
  path: "/api/products/search",
  method: "GET",
  schema: ProductSchema,
  mock: {
    count: 10,
    instruction: "Generate products matching search query: {{query}}, category: {{category}}"
  }
});

const results = await searchProducts({
  query: "laptop",
  category: "electronics"
});
```

**2. User-Specific Data**

```typescript
export const getUserOrders = defineMockEndpoint<Order[]>({
  path: "/api/users/:userId/orders",
  method: "GET",
  schema: OrderSchema,
  mock: {
    count: 5,
    instruction: "Generate orders for user with role: {{userRole}}, status: {{status}}"
  }
});

const orders = await getUserOrders({
  userId: "123",
  userRole: "premium",
  status: "completed"
});
```

**3. Date Ranges**

```typescript
export const getAnalytics = defineMockEndpoint<Analytics>({
  path: "/api/analytics",
  method: "GET",
  schema: AnalyticsSchema,
  mock: {
    instruction: "Generate analytics data for period {{startDate}} to {{endDate}}"
  }
});

const data = await getAnalytics({
  startDate: "2024-01-01",
  endDate: "2024-01-31"
});
```

**4. Localization**

```typescript
export const getContent = defineMockEndpoint<Content[]>({
  path: "/api/content",
  method: "GET",
  schema: ContentSchema,
  mock: {
    count: 10,
    instruction: "Generate content in {{language}} language for {{region}} region"
  }
});

const content = await getContent({
  language: "German",
  region: "Europe"
});
```

### How It Works

1. **Parameters Passed**: Call endpoint with params object
2. **Variables Interpolated**: `{{variable}}` replaced with actual values
3. **AI Generation**: Interpolated instruction sent to AI
4. **Unique Caching**: Each parameter combination cached separately

```typescript
// First call - generates with "active" status
await getOffers({ filter: "active" });

// Second call - cache miss, different params
// Generates new data with "pending" status
await getOffers({ filter: "pending" });

// Third call - cache hit for "active"
await getOffers({ filter: "active" });
```

### Best Practices

**Clear Variable Names**

```typescript
// Good - descriptive
instruction: "Generate {{userType}} users with {{subscriptionTier}} subscription"

// Avoid - unclear
instruction: "Generate {{type}} users with {{tier}}"
```

**Provide Defaults**

```typescript
// Handling missing variables
const params = {
  filter: filter || "all",
  status: status || "active"
};

await getOrders(params);
```

**Combine with Path Parameters**

```typescript
export const getProjectTasks = defineMockEndpoint<Task[]>({
  path: "/api/projects/:projectId/tasks",
  method: "GET",
  schema: TaskSchema,
  mock: {
    instruction: "Generate {{status}} tasks for {{projectType}} project"
  }
});

// Both path param and query params
const tasks = await getProjectTasks({
  projectId: "abc-123",      // Path parameter
  status: "in-progress",     // Instruction variable
  projectType: "enterprise"  // Instruction variable
});
```

## Type Validation

Mockend automatically validates backend responses in production mode:

```typescript
import { TypeValidationError } from "@irmscheremilio/mockend";

try {
  const users = await getUsers();
} catch (error) {
  if (error instanceof TypeValidationError) {
    console.error("Validation failed at:", error.path);
    console.error("Expected:", error.expected);
    console.error("Received:", error.received);
  }
}
```

## Documentation

For full documentation, visit the [main repository](https://github.com/yourusername/mockend).

## License

MIT