@pod-protocol/cli
Version:
Command-line interface for PoD Protocol (Prompt or Die) AI Agent Communication Protocol
168 lines (167 loc) • 4.97 kB
JavaScript
import { PublicKey } from "@solana/web3.js";
import chalk from "chalk";
/**
* Validation error class for CLI operations
*/
export class ValidationError extends Error {
constructor(message) {
super(message);
this.name = "ValidationError";
}
}
/**
* Validate a Solana public key address
*/
export function validatePublicKey(address, fieldName = "address") {
try {
return new PublicKey(address);
}
catch {
throw new ValidationError(`Invalid ${fieldName}: ${address}`);
}
}
/**
* Validate SOL amount (must be positive)
*/
export function validateSolAmount(amount, fieldName = "amount") {
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
if (isNaN(numAmount)) {
throw new ValidationError(`Invalid ${fieldName}: must be a number`);
}
if (numAmount <= 0) {
throw new ValidationError(`Invalid ${fieldName}: must be positive`);
}
if (numAmount > 1000000) {
throw new ValidationError(`Invalid ${fieldName}: amount too large`);
}
return numAmount;
}
/**
* Validate capabilities bitmask
*/
export function validateCapabilities(capabilities) {
const numCaps = typeof capabilities === "string"
? parseInt(capabilities, 10)
: capabilities;
if (isNaN(numCaps)) {
throw new ValidationError("Invalid capabilities: must be a number");
}
if (numCaps < 0) {
throw new ValidationError("Invalid capabilities: must be non-negative");
}
if (numCaps > 255) {
throw new ValidationError("Invalid capabilities: value too large");
}
return numCaps;
}
/**
* Validate URI format
*/
export function validateUri(uri, fieldName = "URI") {
if (!uri.trim()) {
throw new ValidationError(`${fieldName} cannot be empty`);
}
try {
new URL(uri);
return uri.trim();
}
catch {
// Allow relative paths and simple strings for metadata URIs
if (uri.length > 500) {
throw new ValidationError(`${fieldName} too long (max 500 characters)`);
}
return uri.trim();
}
}
/**
* Validate channel name
*/
export function validateChannelName(name) {
if (!name.trim()) {
throw new ValidationError("Channel name cannot be empty");
}
if (name.length > 32) {
throw new ValidationError("Channel name too long (max 32 characters)");
}
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
throw new ValidationError("Channel name can only contain letters, numbers, underscores, and hyphens");
}
return name.trim();
}
/**
* Validate message content
*/
export function validateMessage(content) {
if (!content.trim()) {
throw new ValidationError("Message content cannot be empty");
}
if (content.length > 10000) {
throw new ValidationError("Message too long (max 10,000 characters)");
}
return content.trim();
}
/**
* Validate network name
*/
export function validateNetwork(network) {
const validNetworks = ["devnet", "testnet", "mainnet-beta", "localnet"];
if (!validNetworks.includes(network)) {
throw new ValidationError(`Invalid network: ${network}. Must be one of: ${validNetworks.join(", ")}`);
}
return network;
}
/**
* Validate file path exists and is readable
*/
export function validateFilePath(filePath, fieldName = "file") {
if (!filePath.trim()) {
throw new ValidationError(`${fieldName} path cannot be empty`);
}
// Basic path validation - more thorough checks should be done with fs
if (filePath.includes("..") && !filePath.startsWith("~/")) {
console.warn(chalk.yellow(`Warning: ${fieldName} path contains '..' - ensure this is intentional`));
}
return filePath.trim();
}
/**
* Validate positive integer
*/
export function validatePositiveInteger(value, fieldName = "value") {
const num = typeof value === "string" ? parseInt(value, 10) : value;
if (isNaN(num) || !Number.isInteger(num)) {
throw new ValidationError(`Invalid ${fieldName}: must be an integer`);
}
if (num <= 0) {
throw new ValidationError(`Invalid ${fieldName}: must be positive`);
}
return num;
}
/**
* Validate enum value
*/
export function validateEnum(value, validValues, fieldName = "value") {
if (!validValues.includes(value)) {
throw new ValidationError(`Invalid ${fieldName}: ${value}. Must be one of: ${validValues.join(", ")}`);
}
return value;
}
/**
* Safe validation wrapper that catches and formats errors
*/
export function safeValidate(validator, onError) {
try {
return validator();
}
catch (error) {
if (error instanceof ValidationError) {
if (onError) {
onError(error);
}
else {
console.error(chalk.red("Validation Error:"), error.message);
}
return null;
}
throw error;
}
}