npm package: @scarif/scarif-js
Description: A TypeScript SDK for Scarif API services
Author: GeneralTyres
Latest version: 1.0.3

# Scarif API SDK

Type-safe SDK for Scarif API services with chainable querying. Create a client with your API key (e.g. from your app's env), then use `client.from()` and `client.health()` — same pattern as Supabase.

## Installation

```bash
npm install @scarif/scarif-js
```

## Quick Start

Create a client with your API key (from your app's environment), then query via the client:

```javascript
import { createClient } from '@scarif/scarif-js';

const client = createClient({
  apiKey: process.env.API_KEY
});

const { data, error } = await client.from('countries').select('*');
```

Optional options: `baseUrl`, `timeout` (default 30000ms).

## Features

- **Type-Safe** - Full TypeScript support with automatic type inference
- **Chainable API** - Supabase-like query builder
- **Lightweight** - Minimal dependencies
- **Relations** - Eager loading via select syntax

## Querying & Filtering

### Basic Queries

```javascript
const client = createClient({ apiKey: process.env.API_KEY });

const { data: all } = await client.from('countries').select('*');
const { data: names } = await client.from('countries').select('name, iso');
```

### Relations (Eager Loading)

```javascript
const { data: withCities } = await client.from('countries').select('*, cities(*)');
const { data: custom } = await client.from('countries').select('name, iso, cities(id, name, population)');
const { data: multiple } = await client.from('countries').select('*, cities(*), languages(*)');
```

### Filtering

```javascript
const { data: usa } = await client.from('countries').select('*').eq('iso', 'US');
const { data: notUSA } = await client.from('countries').select('*').neq('iso', 'US');
const { data: highIds } = await client.from('countries').select('*').gt('id', 100);
const { data: united } = await client.from('countries').select('*').ilike('name', '%united%');
const { data: specific } = await client.from('countries').select('*').in('iso', ['US', 'CA', 'MX']);
const { data: withNull } = await client.from('countries').select('*').isNull('deleted_at');
const { data: withoutNull } = await client.from('countries').select('*').isNotNull('email');
```

### Sorting

```javascript
const { data: sorted } = await client.from('countries').select('*').order('name');
const { data: desc } = await client.from('countries').select('*').order('name', 'desc');
const { data: multi } = await client.from('countries').select('*').order('name', 'asc').order('id', 'desc');
```

### Pagination

```javascript
const { data: limited } = await client.from('countries').select('*').limit(10);
const { data: page2 } = await client.from('countries').select('*').limit(10).offset(10);
```

### Complex Queries

```javascript
const { data, error } = await client
  .from('countries')
  .select('name, iso, cities(id, name), languages(*)')
  .ilike('name', '%united%')
  .order('name', 'asc')
  .limit(10);
```

### Single Result

```javascript
const { data: usa, error } = await client.from('countries').select('*').eq('iso', 'US').single();
```

## TypeScript Support

```typescript
import { createClient } from '@scarif/scarif-js';

const client = createClient({ apiKey: process.env.API_KEY! });

const { data, error } = await client.from('countries').select('*');
data?.forEach(country => {
  console.log(country.name, country.iso);
});

// Custom type for dynamic table
interface CustomRow { id: number; customField: string; }
const { data } = await client.from<CustomRow>('custom_table').select('*');
```

## Error Handling

```javascript
const { data, error } = await client.from('countries').select('*').eq('iso', 'US');
if (error) {
  console.error(error.message, error.code);
} else {
  console.log(data);
}
```

## API Reference

### `createClient(options)`

Creates an API client. **Required** before any data calls.

- `options.apiKey` (required): Your API key (e.g. `process.env.API_KEY`)
- `options.baseUrl` (optional): Base URL (default: `https://stoorplek.onrender.com`)
- `options.timeout` (optional): Request timeout in ms (default: 30000)

**Returns:** `ApiClient` instance.

### `client.from(table)`

Starts a chainable query. Methods: `.select()`, `.eq()`, `.neq()`, `.gt()`, `.gte()`, `.lt()`, `.lte()`, `.like()`, `.ilike()`, `.in()`, `.notIn()`, `.isNull()`, `.isNotNull()`, `.order()`, `.limit()`, `.offset()`, `.range()`, `.single()`.

### `client.health()`

Returns `Promise<ApiResponse>` for the API health endpoint.

## Response Format

```typescript
interface ApiResponse<T> {
  data: T;
  error: { message: string; code?: string; details?: any; } | null;
  status: number;
}
```

## Environment

Create the client once (e.g. at app bootstrap) using your env, then pass the client around:

```javascript
// e.g. in app entry or a shared module
import { createClient } from '@scarif/scarif-js';

export const client = createClient({
  apiKey: process.env.API_KEY
});
```

Use `API_KEY_ENV_VAR` from the package if you want the default env key name: `createClient({ apiKey: process.env[API_KEY_ENV_VAR] })`.

## Available Tables

- `countries` — relations: `cities`, `languages`
- `cities` — relation: `country`
- `languages` — relation: `countries`

## License

MIT