# TypeScript SDK

Official TypeScript/JavaScript SDK for the AIDP API.

## Installation

### npm

```bash
npm install @aidp/sdk
```

### yarn

```bash
yarn add @aidp/sdk
```

### pnpm

```bash
pnpm add @aidp/sdk
```

***

## Quick Start

```typescript
import { AIDPClient } from '@aidp/sdk';

const client = new AIDPClient({
  apiKey: process.env.AIDP_API_KEY,
});

// Search for businesses
const results = await client.search({
  query: 'coffee shops with outdoor seating',
  location: { lat: 45.5231, lon: -122.6765, distance: '5km' },
});

console.log(results.data.businesses);
```

***

## Configuration

### Basic Configuration

```typescript
import { AIDPClient } from '@aidp/sdk';

const client = new AIDPClient({
  apiKey: 'your-api-key',
  environment: 'production', // or 'sandbox'
});
```

### Advanced Configuration

```typescript
const client = new AIDPClient({
  apiKey: process.env.AIDP_API_KEY,
  environment: 'production',
  timeout: 30000, // Request timeout (ms)
  retries: 3, // Number of retries
  retryDelay: 1000, // Initial retry delay (ms)
  maxRetryDelay: 10000, // Max retry delay (ms)
  baseURL: 'https://api.aidp.dev/v1',
  headers: {
    // Custom headers
    'X-Custom-Header': 'value',
  },
});
```

***

## API Methods

### Search

Search for businesses using natural language queries.

```typescript
const results = await client.search({
  query: 'coffee shops',
  location: {
    lat: 45.5231,
    lon: -122.6765,
    distance: '5km',
  },
  category: 'restaurants',
  limit: 10,
  offset: 0,
});

// Response
interface SearchResponse {
  success: boolean;
  data: {
    query: string;
    response: string;
    businesses: Business[];
    total: number;
    sessionId: string;
    pagination: {
      offset: number;
      limit: number;
      hasMore: boolean;
    };
  };
}
```

### Get Business

Get detailed information about a specific business.

```typescript
const business = await client.businesses.get('biz_abc123');

console.log(business.data);
```

### Directory Search

Browse the business directory with filters.

```typescript
const directory = await client.directory({
  category: 'restaurants',
  city: 'Portland',
  state: 'OR',
  verificationLevel: 'verified',
  sortBy: 'aiVisibilityScore',
  limit: 20,
});
```

### Analytics

Get analytics for your business.

```typescript
// Upstream metrics
const upstream = await client.analytics.upstream({
  businessId: 'biz_abc123',
  startDate: '2024-01-01',
  endDate: '2024-12-31',
});

// Intent journeys
const journeys = await client.analytics.intentJourneys({
  businessId: 'biz_abc123',
  period: 'last_30_days',
});

// Attribution
const attribution = await client.analytics.attribution({
  businessId: 'biz_abc123',
  model: 'multi_touch',
});
```

***

## TypeScript Types

The SDK includes full TypeScript definitions:

```typescript
import {
  AIDPClient,
  SearchParams,
  SearchResponse,
  Business,
  Analytics,
  AIDPError,
} from '@aidp/sdk';

// Type-safe parameters
const params: SearchParams = {
  query: 'coffee shops',
  location: { lat: 45.5231, lon: -122.6765, distance: '5km' },
};

// Type-safe response
const response: SearchResponse = await client.search(params);

// Type-safe business data
const business: Business = response.data.businesses[0];
```

***

## Error Handling

### Error Types

```typescript
import { AIDPError, RateLimitError, ValidationError } from '@aidp/sdk';

try {
  const results = await client.search({ query: 'coffee' });
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof ValidationError) {
    console.log('Validation errors:', error.details);
  } else if (error instanceof AIDPError) {
    console.log(`API Error: ${error.message} (${error.code})`);
  } else {
    console.log('Unknown error:', error);
  }
}
```

### Retry Logic

The SDK automatically retries failed requests:

```typescript
const client = new AIDPClient({
  apiKey: process.env.AIDP_API_KEY,
  retries: 3,
  retryDelay: 1000,
  shouldRetry: (error) => {
    // Custom retry logic
    return error.status >= 500 || error.code === 'RATE_LIMIT_EXCEEDED';
  },
});
```

***

## Advanced Usage

### Request Cancellation

```typescript
const controller = new AbortController();

const searchPromise = client.search({ query: 'coffee' }, { signal: controller.signal });

// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000);

try {
  const results = await searchPromise;
} catch (error) {
  if (error.name === 'AbortError') {
    console.log('Request cancelled');
  }
}
```

### Custom Headers

```typescript
const results = await client.search(
  { query: 'coffee' },
  {
    headers: {
      'X-Session-ID': 'session-123',
      'X-User-ID': 'user-456',
    },
  }
);
```

### Pagination

```typescript
async function getAllBusinesses(query: string) {
  const allBusinesses = [];
  let offset = 0;
  const limit = 50;

  while (true) {
    const response = await client.search({
      query,
      limit,
      offset,
    });

    allBusinesses.push(...response.data.businesses);

    if (!response.data.pagination.hasMore) break;
    offset += limit;
  }

  return allBusinesses;
}
```

***

## Framework Integration

### Next.js

```typescript
// app/api/search/route.ts
import { AIDPClient } from '@aidp/sdk';
import { NextRequest, NextResponse } from 'next/server';

const client = new AIDPClient({
  apiKey: process.env.AIDP_API_KEY!,
});

export async function POST(request: NextRequest) {
  const { query, location } = await request.json();

  try {
    const results = await client.search({ query, location });
    return NextResponse.json(results);
  } catch (error) {
    return NextResponse.json({ error: error.message }, { status: error.status || 500 });
  }
}
```

### Express

```typescript
import express from 'express';
import { AIDPClient } from '@aidp/sdk';

const app = express();
const client = new AIDPClient({
  apiKey: process.env.AIDP_API_KEY!,
});

app.post('/api/search', async (req, res) => {
  try {
    const results = await client.search(req.body);
    res.json(results);
  } catch (error) {
    res.status(error.status || 500).json({ error: error.message });
  }
});
```

### React

```typescript
import { AIDPClient } from '@aidp/sdk';
import { useState, useEffect } from 'react';

const client = new AIDPClient({
  apiKey: process.env.REACT_APP_AIDP_API_KEY!
});

function SearchComponent() {
  const [results, setResults] = useState([]);
  const [loading, setLoading] = useState(false);

  const search = async (query: string) => {
    setLoading(true);
    try {
      const response = await client.search({ query });
      setResults(response.data.businesses);
    } catch (error) {
      console.error('Search failed:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <input onChange={(e) => search(e.target.value)} />
      {loading ? 'Loading...' : results.map(b => <div key={b.id}>{b.name}</div>)}
    </div>
  );
}
```

***

## Testing

### Mock Client

```typescript
import { AIDPClient } from '@aidp/sdk';

// Create mock client for testing
const mockClient = {
  search: jest.fn().mockResolvedValue({
    success: true,
    data: {
      businesses: [{ id: 'biz_test', name: 'Test Business' }],
    },
  }),
};

// Use in tests
test('search returns businesses', async () => {
  const results = await mockClient.search({ query: 'coffee' });
  expect(results.data.businesses).toHaveLength(1);
});
```

***

## Need Help?

* 📧 Email: <sdk@aidp.dev>
* 💬 GitHub Discussions: [github.com/aidp/platform/discussions](https://github.com/aidp/platform/discussions)
* 📚 API Reference: [docs.aidp.dev/api](https://docs.aidp.dev/api)
* 🐛 Issues: [github.com/aidp/sdk-js/issues](https://github.com/aidp/sdk-js/issues)
