npm package: @slugkit/sdk
Description: SlugKit SDK for JavaScript/TypeScript applications
Author: SlugKit
Latest version: 1.2.1

# SlugKit SDK

A TypeScript SDK for generating human-readable IDs using SlugKit patterns.

This is the official SDK for the [SlugKit SaaS service](https://dev.slugkit.dev) - a powerful platform for generating unique, human-readable identifiers with configurable patterns.

## Features

- **Pattern Parsing**: Parse and validate SlugKit patterns using the EBNF grammar
- **ID Generation**: Generate random slugs from patterns
- **Dictionary Management**: Fetch dictionary statistics and tags
- **Rate Limiting**: Automatic tracking of API rate limits with error handling
- **Type Safety**: Full TypeScript support with comprehensive type definitions

## Installation

```bash
npm install @slugkit/sdk
```

## Usage

### Basic Setup

```typescript
import { SlugKit } from '@slugkit/sdk';

// Create a SlugKit instance with API key (recommended for MCP servers)
const slugkit = SlugKit.fromApiKey('https://dev.slugkit.dev', 'your-api-key');

// Or create from JWK for SDK authentication
const slugkit = await SlugKit.fromJwk('https://dev.slugkit.dev', 'your-sdk-slug', jwkObject);

// Or use automatic key fetching from backend
const slugkit = await SlugKit.fromBackend('https://dev.slugkit.dev', 'your-sdk-slug');
```

### Generating Slugs

```typescript
// Generate random slugs using forge
const slugs = await slugkit.forgeSlugs('{noun}', 5);
console.log(slugs); // Array of 5 random nouns

// Generate with seed for reproducible results
const deterministicSlugs = await slugkit.forgeSlugs('{noun}', 3, 'my-seed');

// Generate with sequence offset
const offsetSlugs = await slugkit.forgeSlugs('{noun}', 2, undefined, 100);

// Mint slugs from a series (if available)
const mintedSlugs = await slugkit.mintSlugs('my-series', 5);

// Slice slugs (dry-run preview)
const slicedSlugs = await slugkit.sliceSlugs('my-series', 3, 1000, 0);

// Get pattern info (includes capacity and more details)
const patternInfo = await slugkit.getPatternInfo('{noun}');
console.log(patternInfo.capacity); // Number of possible combinations
console.log(patternInfo.max_slug_length); // Maximum length of generated slugs
console.log(patternInfo.complexity); // Pattern complexity score
console.log(patternInfo.components); // Number of components in pattern
```

### Pattern Parsing

```typescript
import { PatternParser } from '@slugkit/sdk';

// Parse a pattern
const parsed = PatternParser.parse('{noun} {adjective}');
console.log(parsed.elements); // Array of pattern elements

// Validate a pattern without throwing
const isValid = PatternParser.validate('{noun}');
console.log(isValid); // true/false
```

### Dictionary Management

```typescript
// Get dictionary statistics (cached after first call)
const stats = await slugkit.getDictionaries();
console.log(stats);
// [
//   { kind: 'noun', lang: 'en', word_count: 1000, tag_count: 15 },
//   { kind: 'adjective', lang: 'en', word_count: 500, tag_count: 12 }
// ]

// Get dictionary tags (cached after first call)
const tags = await slugkit.getDictionaryTags();
console.log(tags);
// [
//   {
//     kind: 'noun',
//     tag: 'formal',
//     description: 'Formal language',
//     opt_in: true,
//     word_count: 100
//   }
// ]

// Force fresh data (bypass cache)
const freshStats = await slugkit.fetchDictionaries();
const freshTags = await slugkit.fetchDictionaryTags();
```

### Rate Limiting

The SDK automatically tracks rate limiting information from API responses and provides enhanced error handling for rate limit exceeded scenarios.

```typescript
// Check current rate limits after any API call
const rateLimits = slugkit.getRateLimitInfo();
if (rateLimits) {
  console.log('RPM remaining:', rateLimits.rpmRemaining); // -1 = unlimited
  console.log('Daily remaining:', rateLimits.dailyRemaining); // -1 = unlimited
  console.log('Monthly remaining:', rateLimits.monthlyRemaining); // -1 = unlimited
  console.log('Lifetime remaining:', rateLimits.lifetimeRemaining); // -1 = unlimited
}

// Handle rate limit errors with detailed information
try {
  const slugs = await slugkit.forgeSlugs('{noun}', 1000);
} catch (error) {
  if (error.retryAfter) {
    console.log(`Rate limited! Retry after ${error.retryAfter} seconds`);
    console.log('Reason:', error.rateLimitReason);

    // Access current limits even in error case
    if (error.rateLimitInfo) {
      console.log('Current RPM remaining:', error.rateLimitInfo.rpmRemaining);
    }
  }
}
```

## API Reference

### PatternParser

- `parse(pattern: string): ParsedPattern` - Parse a pattern string
- `validate(pattern: string): boolean` - Validate a pattern without throwing

### SlugKit

#### Static Factory Methods
- `SlugKit.fromApiKey(backend: string, apiKey: string): SlugKit` - Create instance with API key
- `SlugKit.fromJwk(backend: string, sdkSlug: string, jwk: JsonWebKey): Promise<SlugKit>` - Create from JWK
- `SlugKit.fromBackend(backend: string, sdkSlug: string): Promise<SlugKit>` - Create with auto key fetching

#### Dictionary Methods
- `getDictionaries(): Promise<DictionaryStats[]>` - Get dictionary statistics (cached)
- `getDictionaryTags(): Promise<DictionaryTag[]>` - Get dictionary tags (cached)
- `fetchDictionaries(): Promise<DictionaryStats[]>` - Get dictionary statistics (fresh)
- `fetchDictionaryTags(): Promise<DictionaryTag[]>` - Get dictionary tags (fresh)

#### Generation Methods
- `forgeSlugs(pattern: string, count: number, seed?: string, sequence?: number): Promise<string[]>` - Generate random slugs
- `mintSlugs(seriesSlug?: string, count: number, batchSize?: number): Promise<string[]>` - Mint from series
- `sliceSlugs(seriesSlug?: string, count: number, batchSize?: number, sequence?: number): Promise<string[]>` - Slice preview
- `getPatternInfo(pattern: string): Promise<PatternInfo>` - Get pattern analysis

#### Rate Limiting Methods
- `getRateLimitInfo(): RateLimitInfo | null` - Get current rate limiting status

## Types

### DictionaryStats
```typescript
interface DictionaryStats {
  kind: string;
  lang: string;
  word_count: number;
  tag_count: number;
}
```

### DictionaryTag
```typescript
interface DictionaryTag {
  kind: string;
  tag: string;
  description: string;
  opt_in: boolean;
  word_count: number;
}
```

### PatternInfo
```typescript
interface PatternInfo {
  pattern: string;
  capacity: string;
  max_slug_length: number;
  complexity: number;
  components: number;
}
```

### RateLimitInfo
```typescript
interface RateLimitInfo {
  rpmRemaining: number;      // Requests per minute remaining (-1 = unlimited)
  dailyRemaining: number;    // Daily requests remaining (-1 = unlimited)
  monthlyRemaining: number;  // Monthly requests remaining (-1 = unlimited)
  lifetimeRemaining: number; // Lifetime requests remaining (-1 = unlimited)
}
```

### RateLimitError
```typescript
interface RateLimitError extends Error {
  rateLimitReason?: string;  // Human-readable rate limit reason
  retryAfter?: number;       // Seconds to wait before retrying
  rateLimitInfo?: RateLimitInfo; // Current rate limit status
}
```

## Pattern Grammar

The SDK supports the full SlugKit EBNF grammar for patterns:

- **Selectors**: `{noun@en:+formal -nsfw >3,case=lower}`
- **Number Generators**: `{number:5,hex}` or `{number:5d}`
- **Special Characters**: `{special:3-5}`
- **Global Settings**: `[@en +formal >3,case=lower]`

## Error Handling

The SDK provides comprehensive error handling:

```typescript
try {
  const result = await slugkit.getDictionaries();
} catch (error) {
  if (error.message.includes('Authentication failed')) {
    // Handle auth errors - may trigger automatic key refresh
  } else if (error.message.includes('Network error')) {
    // Handle network errors
  } else if (error.retryAfter) {
    // Enhanced rate limiting error handling
    console.log(`Rate limited! Retry after ${error.retryAfter} seconds`);
    console.log('Reason:', error.rateLimitReason);

    // Check current limits even during errors
    if (error.rateLimitInfo) {
      console.log('RPM remaining:', error.rateLimitInfo.rpmRemaining);
    }
  }
}

// Pattern validation errors
try {
  const info = await slugkit.getPatternInfo('{invalid-pattern}');
} catch (error) {
  console.log('Pattern validation failed:', error.message);
}

// Rate limiting status monitoring
const rateLimits = slugkit.getRateLimitInfo();
if (rateLimits) {
  // Warn when approaching limits
  if (rateLimits.rpmRemaining !== -1 && rateLimits.rpmRemaining < 10) {
    console.warn('Approaching RPM limit:', rateLimits.rpmRemaining);
  }
}
```

## Testing

```bash
npm test
```

## Building

```bash
npm run build
```