API Client for use with Scramjet Transform Hub providing typed interfaces for managing sequences, instances, and Hub operations
—
The ManagerClient provides advanced operations for multi-hub environments including hub management, distributed store operations, and cross-hub monitoring.
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");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);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`);
}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}`);
}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>;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);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;
};
};
}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({});
}
}
}
}
}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