npm package: @martiangreedcartridge/sdk
Description: TypeScript/JavaScript client library and CLI for Torii gRPC services
Latest version: 0.1.0

# @toriijs/sdk

TypeScript/JavaScript client library and CLI for Torii gRPC services.

## Installation

```bash
bun add @toriijs/sdk
# or
npm install @toriijs/sdk
```

## Quick Start

### 1. Generate clients from your Torii server

```bash
# From gRPC reflection (server must be running)
bunx torii.js --url http://localhost:8080 --output ./generated

# Or from proto files
bunx torii.js ./path/to/protos --output ./generated
```

### 2. Use the generated clients

```typescript
import { ToriiClient } from "@toriijs/sdk";
import { SqlSinkClient, LogSinkClient } from "./generated";

// Create client with plugins
const client = new ToriiClient("http://localhost:8080", {
  sql: SqlSinkClient,
  log: LogSinkClient,
});

// Core methods (always available)
const version = await client.getVersion();
const topics = await client.listTopics();

// Plugin methods (fully typed!)
const result = await client.sql.query({ query: "SELECT * FROM users" });

// Subscribe to topics
const unsubscribe = await client.subscribeTopics(
  "my-client-id",
  [{ topic: "sql", filters: { table: "users" } }],
  (update) => console.log("Update:", update),
  (error) => console.error("Error:", error),
  () => console.log("Connected!")
);

// Later: unsubscribe
unsubscribe();
```

## CLI Usage

```bash
torii.js [options]              # Generate from gRPC reflection
torii.js <path> [options]       # Generate from proto files
```

### Options

| Option | Description | Default |
|--------|-------------|---------|
| `[path]` | Path to search for .proto files | - |
| `--url` | Server URL for reflection | `http://localhost:8080` |
| `--output`, `-o` | Output directory | `./generated` |
| `--sdk-import` | SDK import path in generated code | `@toriijs/sdk` |

### Examples

```bash
# Generate from running server
bunx torii.js --url http://localhost:8080

# Generate from proto files
bunx torii.js ./protos --output ./src/generated

# Local development (import from relative path)
bunx torii.js ./protos --sdk-import ../node_modules/@toriijs/sdk
```

## Architecture

```
@toriijs/sdk
├── ToriiClient        # Main client with plugin support
├── BaseSinkClient     # Base class for generated clients
└── GrpcTransport      # gRPC-Web transport layer

./generated (CLI output)
├── SqlSinkClient.ts   # Generated, extends BaseSinkClient
├── LogSinkClient.ts   # Generated, extends BaseSinkClient
└── index.ts           # Re-exports all clients
```

## API Reference

### ToriiClient

```typescript
const client = new ToriiClient(baseUrl, plugins);

// Core methods
client.getVersion(): Promise<{ version, buildTime }>
client.listTopics(): Promise<Topic[]>
client.subscribeTopics(clientId, topics, onUpdate, onError?, onConnected?): Promise<() => void>
client.disconnect(): void

// Plugin access (typed based on plugins passed to constructor)
client.sql.query(...)   // If SqlSinkClient was passed
client.log.queryLogs(...) // If LogSinkClient was passed
```

### BaseSinkClient

Base class for generated clients. Provides:

```typescript
protected unaryCall<T>(path, request, options?): Promise<T>
protected streamCall<T>(path, request, options?): AsyncGenerator<T>
protected subscribeWithCallbacks<T>(path, request, onMessage, onError?, onConnected?): Promise<() => void>
```

## Generated Client Example

```typescript
// Generated by CLI
import { BaseSinkClient, type CallOptions } from "@toriijs/sdk";

export class SqlSinkClient extends BaseSinkClient {
  async query(request = {}, options?: CallOptions) {
    return this.unaryCall('/torii.sinks.sql.SqlSink/Query', request, options);
  }

  async *streamQuery(request = {}, options?: CallOptions) {
    yield* this.streamCall('/torii.sinks.sql.SqlSink/StreamQuery', request, options);
  }
}
```