CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-scramjet--api-client

API Client for use with Scramjet Transform Hub providing typed interfaces for managing sequences, instances, and Hub operations

Pending
Overview
Eval results
Files

manager-client.mddocs/

Manager Operations

The ManagerClient provides advanced operations for multi-hub environments including hub management, distributed store operations, and cross-hub monitoring.

Capabilities

Manager Client Creation

Create a ManagerClient for advanced Hub management operations.

/**
 * Creates a new ManagerClient instance for advanced Hub management
 * @param apiBase - Base URL for the Manager API (e.g., "http://localhost:8001/api/v1")
 * @param utils - Optional custom ClientUtils instance for advanced configuration
 */
class ManagerClient implements ClientProvider {
  constructor(apiBase: string, utils?: ClientUtils);
  
  readonly apiBase: string;
  readonly client: ClientUtils;
}

Usage Example:

import { ManagerClient } from "@scramjet/api-client";

const manager = new ManagerClient("http://localhost:8001/api/v1");

Hub Management

Manage multiple Transform Hub instances in a distributed environment.

/**
 * Gets information about all connected Hubs
 * @returns Promise resolving to array of Hub information
 */
getHosts(): Promise<MRestAPI.GetHostInfoResponse[]>;

/**
 * Creates a HostClient for a specific Hub
 * @param id - Hub identifier
 * @param hostApiBase - Optional API base path for the Hub (defaults to "/api/v1")
 * @returns HostClient instance configured for the specified Hub
 */
getHostClient(id: string, hostApiBase?: string): HostClient;

/**
 * Deletes a Hub from the Manager
 * @param id - Hub identifier
 * @param force - Whether to force deletion even if Hub has running instances
 * @returns Promise resolving to deletion result
 */
deleteHub(id: string, force: boolean): Promise<MRestAPI.HubDeleteResponse>;

/**
 * Disconnects Hubs based on specified criteria
 * @param opts - Disconnection options and criteria
 * @returns Promise resolving to disconnection results
 */
disconnectHubs(opts: MRestAPI.PostDisconnectPayload): Promise<MRestAPI.PostDisconnectResponse>;

Usage Examples:

// List all connected Hubs
const hubs = await manager.getHosts();
console.log(`Connected to ${hubs.length} Hubs:`);
hubs.forEach(hub => {
  console.log(`- ${hub.id}: ${hub.address} (${hub.status})`);
});

// Get a client for a specific Hub
const specificHub = manager.getHostClient("hub-001");
const sequences = await specificHub.listSequences();

// Remove a disconnected Hub
await manager.deleteHub("hub-002", true);

Cross-Hub Operations

Query and manage resources across all connected Hubs.

/**
 * Gets all sequences across all connected Hubs
 * @returns Promise resolving to comprehensive sequence list
 */
getAllSequences(): Promise<MRestAPI.GetSequencesResponse>;

/**
 * Gets sequences from the Manager's perspective
 * @returns Promise resolving to Manager-tracked sequences
 */
getSequences(): Promise<MRestAPI.GetSequencesResponse>;

/**
 * Gets all instances across all connected Hubs
 * @returns Promise resolving to comprehensive instance list
 */
getInstances(): Promise<MRestAPI.GetInstancesResponse>;

/**
 * Gets all topics across all connected Hubs
 * @returns Promise resolving to comprehensive topics list
 */
getTopics(): Promise<MRestAPI.GetTopicsResponse>;

Usage Examples:

// Get global view of all resources
const allSequences = await manager.getAllSequences();
console.log(`Total sequences across all Hubs: ${allSequences.length}`);

const allInstances = await manager.getInstances();
const runningInstances = allInstances.filter(i => i.status === "running");
console.log(`Running instances: ${runningInstances.length}/${allInstances.length}`);

// Find instances by sequence name across all Hubs
const targetSequences = allSequences.filter(s => s.config.name === "data-processor");
for (const seq of targetSequences) {
  console.log(`Hub ${seq.hubId}: sequence ${seq.id} has ${seq.instances.length} instances`);
}

Distributed Store Operations

Manage shared storage across the Hub network.

/**
 * Gets all items from the distributed store
 * @returns Promise resolving to store items list
 */
getStoreItems(): Promise<MRestAPI.GetStoreItemsResponse>;

/**
 * Uploads an item to the distributed store
 * @param sequencePackage - Stream containing the data to store
 * @param id - Optional identifier for the stored item
 * @returns Promise resolving to store operation result
 */
putStoreItem(
  sequencePackage: Readable,
  id?: string
): Promise<MRestAPI.PutStoreItemResponse>;

/**
 * Deletes an item from the distributed store
 * @param id - Identifier of the item to delete
 * @returns Promise resolving when deletion is complete
 */
deleteStoreItem(id: string): Promise<void>;

/**
 * Clears all items from the distributed store
 * @returns Promise resolving when store is cleared
 */
clearStore(): Promise<void>;

Usage Examples:

import fs from "fs";

// Upload a sequence package to shared store
const packageStream = fs.createReadStream("./shared-utility.tar.gz");
const storeResult = await manager.putStoreItem(packageStream, "shared-utility-v1.0");
console.log(`Stored item: ${storeResult.id}`);

// List all stored items
const storeItems = await manager.getStoreItems();
storeItems.forEach(item => {
  console.log(`- ${item.id}: ${item.size} bytes, uploaded ${item.created}`);
});

// Clean up old items
const oldItems = storeItems.filter(item => 
  new Date(item.created) < new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) // 30 days
);
for (const item of oldItems) {
  await manager.deleteStoreItem(item.id);
  console.log(`Removed old item: ${item.id}`);
}

System Monitoring

Monitor system-wide metrics and health across all Hubs.

/**
 * Gets Manager version information
 * @returns Promise resolving to version details
 */
getVersion(): Promise<MRestAPI.GetVersionResponse>;

/**
 * Gets aggregate load statistics across all Hubs
 * @returns Promise resolving to load statistics
 */
getLoad(): Promise<LoadCheckStat>;

/**
 * Gets Manager configuration
 * @returns Promise resolving to configuration data
 */
getConfig(): Promise<any>;

Streaming Operations

Access aggregated log and audit streams from all Hubs.

/**
 * Gets aggregated log stream from all connected Hubs
 * @param requestInit - Optional request configuration
 * @returns Promise resolving to aggregated log stream
 */
getLogStream(requestInit?: RequestInit): Promise<Readable>;

/**
 * Gets aggregated audit stream from all connected Hubs
 * @param requestInit - Optional request configuration
 * @returns Promise resolving to aggregated audit stream
 */
getAuditStream(requestInit?: RequestInit): Promise<Readable>;

/**
 * Sends data to a named topic across the Hub network
 * @param topic - Topic name
 * @param stream - Data stream to send
 * @param requestInit - Optional request configuration
 * @param contentType - Content type
 * @param end - Whether to signal end of stream
 * @returns Promise resolving to send result
 */
sendNamedData<T>(
  topic: string,
  stream: Parameters<HttpClient["sendStream"]>[1],
  requestInit?: RequestInit,
  contentType?: string,
  end?: boolean
): Promise<T>;

/**
 * Gets data stream from a named topic across the Hub network
 * @param topic - Topic name
 * @param requestInit - Optional request configuration
 * @returns Promise resolving to topic data stream
 */
getNamedData(topic: string, requestInit?: RequestInit): Promise<Readable>;

Usage Examples:

// Monitor aggregate system logs
const logStream = await manager.getLogStream();
logStream.on('data', (chunk) => {
  const logEntry = JSON.parse(chunk.toString());
  console.log(`[${logEntry.hubId}] ${logEntry.level}: ${logEntry.message}`);
});

// Broadcast configuration updates
const configStream = Readable.from([JSON.stringify({
  action: "update-config",
  config: { logLevel: "debug" }
})]);
await manager.sendNamedData("system-config", configStream);

Response Types

interface MRestAPI {
  GetHostInfoResponse: {
    id: string;
    address: string;
    status: "connected" | "disconnected" | "error";
    version: string;
    load: {
      avgLoad: number[];
      currentLoad: number;
      memUsage: number;
    };
    sequences: number;
    instances: number;
    uptime: number;
    [key: string]: any;
  };
  
  GetSequencesResponse: Array<{
    id: string;
    hubId: string;
    config: {
      name: string;
      version: string;
      [key: string]: any;
    };
    instances: string[];
  }>;
  
  GetInstancesResponse: Array<{
    id: string;
    hubId: string;
    sequenceId: string;
    status: "starting" | "running" | "stopping" | "stopped" | "crashed";
    created: string;
    [key: string]: any;
  }>;
  
  GetTopicsResponse: Array<{
    id: string;
    hubId: string;
    contentType: string;
    subscribers: number;
    [key: string]: any;
  }>;
  
  GetStoreItemsResponse: Array<{
    id: string;
    size: number;
    created: string;
    checksum: string;
    [key: string]: any;
  }>;
  
  PutStoreItemResponse: {
    id: string;
    size: number;
    checksum: string;
  };
  
  HubDeleteResponse: {
    id: string;
    message: string;
    deleted: boolean;
  };
  
  PostDisconnectPayload: {
    criteria: {
      status?: "disconnected" | "error";
      olderThan?: string; // ISO date string
      hubIds?: string[];
    };
    force?: boolean;
  };
  
  PostDisconnectResponse: {
    disconnected: string[];
    errors: Array<{
      hubId: string;
      error: string;
    }>;
  };
  
  GetVersionResponse: {
    version: string;
    build?: string;
    components: {
      [componentName: string]: string;
    };
  };
}

Advanced Patterns

Multi-Hub Deployment Management

class MultiHubDeployment {
  constructor(private manager: ManagerClient) {}
  
  async deployToAllHubs(packagePath: string, config: any) {
    const hubs = await this.manager.getHosts();
    const deployments = [];
    
    for (const hub of hubs.filter(h => h.status === "connected")) {
      try {
        const hostClient = this.manager.getHostClient(hub.id);
        const packageStream = fs.createReadStream(packagePath);
        const sequence = await hostClient.sendSequence(packageStream);
        const instance = await sequence.start(config);
        
        deployments.push({
          hubId: hub.id,
          sequenceId: sequence.id,
          instanceId: instance.id
        });
      } catch (error) {
        console.error(`Failed to deploy to hub ${hub.id}:`, error.message);
      }
    }
    
    return deployments;
  }
  
  async scaleAcrossHubs(sequenceName: string, targetInstances: number) {
    const sequences = await this.manager.getAllSequences();
    const targetSequences = sequences.filter(s => s.config.name === sequenceName);
    
    for (const seq of targetSequences) {
      const currentInstances = seq.instances.length;
      const needed = Math.max(0, targetInstances - currentInstances);
      
      if (needed > 0) {
        const hubClient = this.manager.getHostClient(seq.hubId);
        const sequenceClient = hubClient.getSequenceClient(seq.id);
        
        for (let i = 0; i < needed; i++) {
          await sequenceClient.start({});
        }
      }
    }
  }
}

Distributed Load Monitoring

async function monitorClusterHealth(manager: ManagerClient) {
  const hubs = await manager.getHosts();
  const aggregateLoad = await manager.getLoad();
  
  console.log(`Cluster Overview:`);
  console.log(`- Total Hubs: ${hubs.length}`);
  console.log(`- Aggregate Load: ${aggregateLoad.currentLoad.toFixed(2)}`);
  console.log(`- Memory Usage: ${aggregateLoad.memUsage.toFixed(1)}%`);
  
  // Check for overloaded hubs
  const overloadedHubs = hubs.filter(hub => hub.load.currentLoad > 0.8);
  if (overloadedHubs.length > 0) {
    console.log(`⚠️  Overloaded Hubs (>80% CPU):`);
    overloadedHubs.forEach(hub => {
      console.log(`   - ${hub.id}: ${(hub.load.currentLoad * 100).toFixed(1)}% CPU`);
    });
  }
  
  // Check for disconnected hubs
  const disconnectedHubs = hubs.filter(hub => hub.status !== "connected");
  if (disconnectedHubs.length > 0) {
    console.log(`❌ Disconnected Hubs:`);
    disconnectedHubs.forEach(hub => {
      console.log(`   - ${hub.id}: ${hub.status}`);
    });
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-scramjet--api-client

docs

host-client.md

index.md

instance-client.md

manager-client.md

sequence-client.md

topics.md

tile.json