npm package: @scriptdb/client
Description: Client module resolver for script database
Latest version: 1.1.3

# ScriptDB Client

Client module for connecting to and interacting with ScriptDB servers.

## Installation

```bash
npm install @scriptdb/client
# or
yarn add @scriptdb/client
# or
bun add @scriptdb/client
```

## Quick Start

```typescript
import { ScriptDBClient } from '@scriptdb/client';

// Create a client instance
const client = new ScriptDBClient('scriptdb://localhost:1234/mydatabase', {
  username: 'admin',
  password: 'password'
});

// Connect to the server
await client.connect();

// Execute a command
const result = await client.execute('getUsers');
console.log(result);

// Close the connection when done
client.close();
```

## API Reference

### Constructor

```typescript
new ScriptDBClient(uri, options?)
```

- `uri` (string): Connection URI in format `scriptdb://host:port/database`
- `options` (ClientOptions, optional): Configuration options

#### URI Format

The URI follows the pattern: `scriptdb://[username:password@]host:port/database`

Examples:
- `scriptdb://localhost:1234/mydb`
- `scriptdb://user:pass@localhost:1234/mydb`
- `scriptdb://example.com:8080/production`

### Options

```typescript
interface ClientOptions {
  secure?: boolean;              // Use TLS (default: true)
  logger?: Logger;               // Custom logger
  requestTimeout?: number;       // Request timeout in ms (default: 0 = no timeout)
  socketTimeout?: number;        // Socket timeout in ms (default: 0 = no timeout)
  retries?: number;              // Reconnection retries (default: 3)
  retryDelay?: number;           // Initial retry delay in ms (default: 1000)
  tlsOptions?: tls.TlsOptions;   // TLS options when secure=true
  frame?: 'ndjson' | 'length-prefix';  // Message framing (default: 'ndjson')
  preferLengthPrefix?: boolean;  // Use length-prefixed framing (alias for frame)
  maxPending?: number;           // Max concurrent requests (default: 100)
  maxQueue?: number;             // Max queued requests (default: 1000)
  maxMessageSize?: number;       // Max message size in bytes (default: 5MB)
  signing?: {                    // Message signing options
    secret: string;
    algorithm?: string;          // Default: 'sha256'
  };
  stringify?: (obj: any) => string; // Custom stringify function
  username?: string;             // Username (overrides URI)
  password?: string;             // Password (overrides URI)
  tokenRefresh?: () => Promise<{ token: string; expiresAt?: number }>; // Token refresh
}
```

### Methods

#### connect()

Connects to the server and authenticates.

```typescript
await client.connect(): Promise<ScriptDBClient>
```

Returns a promise that resolves when authentication is successful.

#### execute(command)

Executes a command on the server.

```typescript
await client.execute(command: string): Promise<any>
```

- `command` (string): The command to execute

Returns a promise that resolves with the response data.

#### close()

Closes the connection to the server.

```typescript
client.close(): void
```

#### destroy()

Destroys the client and cleans up resources.

```typescript
client.destroy(): void
```

## Examples

### Basic Usage

```typescript
import { ScriptDBClient } from '@scriptdb/client';

const client = new ScriptDBClient('scriptdb://localhost:1234/testdb', {
  username: 'admin',
  password: 'password123'
});

try {
  await client.connect();
  
  // Execute database commands
  const users = await client.execute('listUsers');
  console.log('Users:', users);
  
  const result = await client.execute('createUser', { name: 'John', email: 'john@example.com' });
  console.log('Created user:', result);
  
} catch (error) {
  console.error('Error:', error.message);
} finally {
  client.close();
}
```

### Secure Connection with TLS

```typescript
import { ScriptDBClient } from '@scriptdb/client';
import { readFileSync } from 'fs';

const client = new ScriptDBClient('scriptdb://secure.example.com:443/production', {
  secure: true,
  tlsOptions: {
    ca: readFileSync('./ca-cert.pem'),
    cert: readFileSync('./client-cert.pem'),
    key: readFileSync('./client-key.pem'),
    rejectUnauthorized: true
  },
  username: 'admin',
  password: 'secure-password'
});

await client.connect();
```

### Custom Logging

```typescript
import { ScriptDBClient } from '@scriptdb/client';

const client = new ScriptDBClient('scriptdb://localhost:1234/mydb', {
  username: 'user',
  password: 'pass',
  logger: {
    debug: (...args) => console.debug('[DEBUG]', ...args),
    info: (...args) => console.info('[INFO]', ...args),
    warn: (...args) => console.warn('[WARN]', ...args),
    error: (...args) => console.error('[ERROR]', ...args)
  }
});
```

### Message Signing

```typescript
import { ScriptDBClient } from '@scriptdb/client';

const client = new ScriptDBClient('scriptdb://localhost:1234/mydb', {
  username: 'user',
  password: 'pass',
  signing: {
    secret: 'my-secret-key',
    algorithm: 'sha256'
  }
});
```

### Token Refresh

```typescript
import { ScriptDBClient } from '@scriptdb/client';

const client = new ScriptDBClient('scriptdb://localhost:1234/mydb', {
  username: 'user',
  password: 'pass',
  tokenRefresh: async () => {
    // Implement your token refresh logic here
    const response = await fetch('https://api.example.com/refresh-token', {
      method: 'POST',
      headers: { 'Authorization': 'Bearer ' + oldToken }
    });
    const data = await response.json();
    return {
      token: data.token,
      expiresAt: data.expiresAt
    };
  }
});
```

## Error Handling

The client uses promises and will reject with errors for various failure cases:

```typescript
try {
  await client.connect();
} catch (error) {
  if (error.message.includes('Authentication failed')) {
    console.error('Invalid credentials');
  } else if (error.message.includes('ECONNREFUSED')) {
    console.error('Server not reachable');
  } else {
    console.error('Connection error:', error.message);
  }
}
```

## Advanced Features

### Connection Pooling

For high-throughput applications, you can create multiple client instances:

```typescript
const clients = Array.from({ length: 5 }, () => 
  new ScriptDBClient('scriptdb://localhost:1234/mydb', {
    username: 'user',
    password: 'pass'
  })
);

// Connect all clients
await Promise.all(clients.map(client => client.connect()));

// Use round-robin or other strategy to distribute requests
let currentClient = 0;
function getClient() {
  const client = clients[currentClient];
  currentClient = (currentClient + 1) % clients.length;
  return client;
}
```

### Request Queueing

The client automatically queues requests when the number of pending requests exceeds `maxPending`:

```typescript
const client = new ScriptDBClient('scriptdb://localhost:1234/mydb', {
  username: 'user',
  password: 'pass',
  maxPending: 10,      // Max concurrent requests
  maxQueue: 1000       // Max queued requests
});
```

## Development

```bash
# Install dependencies
npm install

# Run tests
npm test

# Build the package
npm run build

# Run type checking
npm run typecheck

# Lint code
npm run lint
```

## CLI Tool

ScriptDB also provides a CLI tool for server management:

```bash
# Install CLI globally
npm install -g @scriptdb/cli

# Start server in foreground
scriptdb start

# Start server in background (daemon mode with PM2)
scriptdb start -d

# Check server status
scriptdb status

# View real-time logs
scriptdb logs

# Monitor performance
scriptdb monit

# Stop server
scriptdb stop

# Restart server
scriptdb restart -d

# Install packages to ScriptDB
scriptdb add lodash
scriptdb add axios express

# Install packages locally
scriptdb add --local lodash
```

### CLI Commands

- `scriptdb start [-d]` - Start the ScriptDB server (`-d` for daemon mode)
- `scriptdb stop` - Stop the running server
- `scriptdb restart [-d]` - Restart the server
- `scriptdb status` - Check server status and view metrics
- `scriptdb logs` - View real-time logs
- `scriptdb monit` - Monitor performance (CPU, memory, uptime)
- `scriptdb shell` - Start interactive shell
- `scriptdb add <package> [--local]` - Install packages
- `scriptdb remove <package> [--local]` - Remove packages

### Configuration

The CLI reads configuration from `~/.scriptdb/config.json`:

```json
{
  "host": "localhost",
  "port": 1234,
  "users": [
    {
      "username": "admin",
      "password": "your-password",
      "hash": false
    }
  ],
  "folder": "databases",
  "secure": false
}
```

## Changelog

### 1.1.2 (2025-01-16)

**Added**
- Native `scriptdb logs` command to view real-time logs
- Native `scriptdb monit` command to monitor performance
- Native `scriptdb restart` command to restart the server
- Native `scriptdb stop` command to stop the server
- Dynamic version reading from package.json

**Fixed**
- Fixed TypeScript module resolution errors
- Fixed test command to continue gracefully when packages have no tests
- Improved error handling and Windows compatibility

## License

MIT