0.2.1 • Published 1 year ago

@kevodb/kevo-sdk v0.2.1

Weekly downloads
-
License
MIT
Repository
-
Last release
1 year ago

🔑 Kevo TypeScript SDK

npm version Node.js Version License

High-performance TypeScript/JavaScript client for the Kevo key-value store.

✨ Features

  • Simple and intuitive API for JavaScript/TypeScript developers
  • Efficient binary protocol (gRPC)
  • Full TypeScript type definitions
  • Transaction support with ACID guarantees
  • Range and prefix scans using async iterators
  • Atomic batch operations
  • Buffer and string interface
  • TLS/SSL support
  • Automatic retries with exponential backoff
  • Smart query routing (reads to replicas, writes to primary)

🚀 Installation

npm install kevo-sdk

Or install from source:

git clone https://github.com/KevoDB/typescript-sdk.git
cd typescript-sdk
npm install
npm run build

🏁 Quick Start

JavaScript

const { KevoClient, KeyNotFoundError } = require('kevo-sdk');

async function main() {
  // Create a client
  const client = new KevoClient({
    host: 'localhost',
    port: 50051,
    // Smart query routing options
    autoRouteReads: true,    // Route reads to replicas when available
    autoRouteWrites: true,   // Route writes to primary
    preferReplica: true      // Prefer replicas for read operations
  });

  try {
    // Connect to the database
    await client.connect();

    // Basic operations
    await client.put('hello', 'world');

    try {
      const value = await client.get('hello');
      console.log(value.toString()); // Prints: world
    } catch (error) {
      if (error instanceof KeyNotFoundError) {
        console.log('Key not found');
      } else {
        throw error;
      }
    }

    // Scan with prefix
    for await (const { key, value } of client.scanPrefix('user:')) {
      console.log(`Key: ${key.toString()}, Value: ${value.toString()}`);
    }

    // Use transactions
    const tx = await client.beginTransaction();
    try {
      await tx.put('key1', 'value1');
      await tx.put('key2', 'value2');
      await tx.commit();
    } catch (error) {
      await tx.rollback();
      throw error;
    }
  } finally {
    // Always disconnect when done
    client.disconnect();
  }
}

main().catch(console.error);

TypeScript

import { KevoClient, ConnectionOptions, KeyNotFoundError } from 'kevo-sdk';

async function main() {
  // Create a client with type-safe options
  const options: ConnectionOptions = {
    host: 'localhost',
    port: 50051,
    // Optional settings
    useTls: false,
    connectTimeout: 5000,
    requestTimeout: 10000,
    maxRetries: 3,
    // Smart query routing options
    autoRouteReads: true,
    autoRouteWrites: true,
    preferReplica: true,
    replicaSelectionStrategy: 'round_robin',
  };

  const client = new KevoClient(options);

  try {
    // Connect to the database
    await client.connect();

    // Basic operations (works with string or Buffer)
    await client.put('counter', '1');
    await client.put(Buffer.from('binary-key'), Buffer.from([0x01, 0x02, 0x03]));

    // Get values
    try {
      // Read operations automatically route to replicas based on client configuration
      const value = await client.get('counter');
      console.log(`Counter: ${value.toString()}`);

      const binaryValue = await client.get('binary-key');
      console.log(`Binary: ${binaryValue.toString('hex')}`);
    } catch (error) {
      if (error instanceof KeyNotFoundError) {
        console.log('Key not found');
      } else {
        throw error;
      }
    }

    // Transaction example
    const tx = await client.beginTransaction({ readOnly: false });
    try {
      const currentValue = await tx.get('counter');
      const newValue = (parseInt(currentValue.toString()) + 1).toString();
      await tx.put('counter', newValue);
      await tx.commit();
    } catch (error) {
      await tx.rollback();
      throw error;
    }
  } finally {
    client.disconnect();
  }
}

main().catch(console.error);

📖 API Reference

KevoClient

const client = new KevoClient(options);

Constructor Options

interface ConnectionOptions {
  host: string;                             // Required: The database host
  port: number;                             // Required: The database port
  useTls?: boolean;                         // Optional: Whether to use TLS (default: false)
  caCert?: Buffer;                          // Optional: CA certificate for TLS
  clientCert?: Buffer;                      // Optional: Client certificate for TLS
  clientKey?: Buffer;                       // Optional: Client key for TLS
  connectTimeout?: number;                  // Optional: Connection timeout in ms (default: 5000)
  requestTimeout?: number;                  // Optional: Request timeout in ms (default: 10000)
  maxRetries?: number;                      // Optional: Maximum number of retries (default: 3)
  retryDelay?: number;                      // Optional: Base delay between retries in ms (default: 1000)
  
  // Smart Query Routing Options
  autoRouteReads?: boolean;                 // Optional: Auto-route reads to replicas (default: true)
  autoRouteWrites?: boolean;                // Optional: Auto-route writes to primary (default: true)
  preferReplica?: boolean;                  // Optional: Prefer replicas for reads (default: true)
  replicaSelectionStrategy?: 'random' | 'sequential' | 'round_robin'; // Optional: How to choose replicas (default: 'round_robin')
}

Core Methods

MethodDescription
connect()Connect to the server
disconnect()Close the connection
isConnected()Check if connected to the server
get(key)Get a value by key
put(key, value, sync?)Store a key-value pair
delete(key, sync?)Delete a key-value pair

Advanced Features

MethodDescription
batch()Create a new batch writer
scanPrefix(prefix, options?)Scan for keys with a prefix
scanRange(start, end, options?)Scan for keys in a range
scan(options?)Low-level scan with custom options
beginTransaction(options?)Begin a new transaction
getStats()Get database statistics
compact()Trigger database compaction

Transaction

Methods

MethodDescription
getId()Get the transaction ID
commit()Commit the transaction
rollback()Roll back the transaction
get(key)Get a value within the transaction
put(key, value)Store a key-value pair within the transaction
delete(key)Delete a key-value pair within the transaction
scan(options?)Scan keys within the transaction
isCommitted()Check if transaction is committed
isRolledBack()Check if transaction is rolled back

BatchWriter

Methods

MethodDescription
put(key, value)Add a put operation to the batch
delete(key)Add a delete operation to the batch
size()Get the number of operations in the batch
clear()Clear all operations from the batch
execute()Execute all operations atomically

Scan Operations

// Prefix scan
for await (const { key, value } of client.scanPrefix('user:')) {
  console.log(`${key.toString()}: ${value.toString()}`);
}

// Range scan
for await (const { key, value } of client.scanRange('user:100', 'user:200')) {
  console.log(`${key.toString()}: ${value.toString()}`);
}

// Scan with options
for await (const { key, value } of client.scan({
  prefix: 'user:',
  limit: 10,
  reverse: true
  // Read operations will automatically route to replicas based on client configuration
})) {
  console.log(`${key.toString()}: ${value.toString()}`);
}

Error Handling

The SDK provides several error classes for specific error cases:

Error ClassDescription
KevoErrorBase error class
ConnectionErrorConnection-related errors
TimeoutErrorTimeout errors
TransactionErrorTransaction-related errors
KeyNotFoundErrorKey not found errors
InvalidArgumentErrorInvalid argument errors
ReadOnlyErrorErrors when attempting write operations on read-only replicas

📋 Examples

Check the examples directory for more detailed examples:

  • 01-basic-operations.js: Basic key-value operations
  • 02-transactions.js: Transaction support with ACID guarantees
  • 03-scanning.js: Scanning operations with prefix and range

🛠️ Development

Prerequisites

  • Node.js 18+
  • npm

Setup

# Install dependencies
npm install

# Build the SDK
npm run build

# Run tests
npm run test

# Run linters
npm run lint

# Check TypeScript types
npm run typecheck

Generating Code from Proto Files

The SDK uses gRPC for communication with the Kevo database. The TypeScript client code is generated from the Protocol Buffer definition file:

# Install protobuf compiler if needed
# For Ubuntu/Debian:
# sudo apt-get install protobuf-compiler
# For macOS:
# brew install protobuf

# Generate the TypeScript client code
npx grpc_tools_node_protoc \
  --js_out=import_style=commonjs,binary:./src/proto \
  --grpc_out=grpc_js:./src/proto \
  --proto_path=./proto \
  ./proto/kevo/service.proto

# Or use the @grpc/proto-loader package as implemented in the SDK
# See connection.ts for implementation details

📄 License

MIT

0.2.1

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago