@ketrics/ketrics-cli
v0.6.1
Published
CLI tool for deploying applications to Ketrics platform
Maintainers
Readme
Ketrics CLI
A command-line tool for creating, building, validating, and deploying applications to the Ketrics serverless platform.
Overview
The Ketrics CLI (@ketrics/ketrics-cli) is a TypeScript-based command-line interface that enables developers to manage their Ketrics applications across the complete application lifecycle. It fits into the Ketrics platform ecosystem as the primary interface for local development and deployment workflows.
Key Responsibilities
- Application Creation: Bootstrap new projects from predefined templates
- Build Orchestration: Compile frontend and backend applications before deployment
- Configuration Management: Load and validate project configuration and environment variables
- Package Bundling: Create optimized ZIP archives with proper file structure and compression
- Deployment Automation: Coordinate the deploy process including API communication and S3 uploads
- Configuration Validation: Verify configuration files and environment setup before operations
- Request Execution: Execute HTTP API requests with variable interpolation and templating
Architecture Boundaries
This component operates as a standalone CLI tool that:
- Does NOT handle cloud infrastructure provisioning (delegated to Ketrics backend)
- Does NOT manage authentication beyond token validation (relies on KETRICS_TOKEN format)
- Does NOT execute or monitor running applications (delegated to Ketrics platform)
- Focuses exclusively on local operations and integration with Ketrics deployment APIs
Project Structure
ketrics-cli/
├── bin/
│ └── ketrics.ts # CLI entry point
├── src/
│ ├── cli.ts # Commander.js setup and command definitions
│ ├── index.ts # Public API exports
│ ├── version.ts # Auto-generated version
│ ├── types/
│ │ └── index.ts # Zod schemas and TypeScript interfaces
│ ├── commands/
│ │ ├── create.ts # Bootstrap new project from template
│ │ ├── build.ts # Build frontend/backend
│ │ ├── deploy.ts # Deploy application
│ │ ├── validate.ts # Validate configuration
│ │ └── run.ts # Execute API requests
│ ├── services/
│ │ ├── config-service.ts # Load/validate ketrics.config.json and .env
│ │ ├── build-service.ts # Orchestrate npm build for frontend/backend
│ │ ├── api-client.ts # HTTP communication with Ketrics API
│ │ ├── zip-service.ts # ZIP archive creation and compression
│ │ ├── upload-service.ts # S3 upload via presigned URLs
│ │ └── template-service.ts # Template discovery and copying
│ └── utils/
│ ├── logger.ts # Colored console output
│ └── spinner.ts # Loading indicators
├── templates/
│ └── HelloWorld/ # Example template for project scaffolding
├── package.json # NPM package configuration
├── tsconfig.json # TypeScript configuration
└── dist/ # Compiled JavaScript (generated)Business Logic
Problem Statement
Developers need a consistent way to:
- Create new Ketrics applications with proper structure
- Build applications locally before deployment
- Package and upload applications to Ketrics infrastructure
- Test API integrations without manual HTTP requests
- Validate configuration before attempting deployments
Core Workflows
1. Application Creation (ketrics create)
Inputs: Application name, optional template name Process:
- Validate app name (alphanumeric, hyphens, underscores; must start with letter)
- Discover available templates from the
templates/directory - Prompt for template selection (interactive or via
--templateflag) - Create application directory
- Copy template files recursively
- Update app name in
ketrics.config.json,frontend/package.json, andbackend/package.json
Outputs: New project directory with template structure Exit on Error: Name validation failure, template not found, directory exists
2. Build Process (ketrics build)
Inputs: Current working directory must contain frontend/ and backend/ subdirectories
Process:
- Validate both directories exist with
node_modulesinstalled - Execute
npm run buildinfrontend/directory - Validate
frontend/dist/was created - Execute
npm run buildinbackend/directory - Validate
backend/dist/was created - Report dist paths to user
Outputs: Built artifacts in frontend/dist/ and backend/dist/
Exit on Error: Missing directories, missing node_modules, build failure, missing dist output
3. Deployment Process (ketrics deploy)
Inputs: Working directory with built frontend/dist/ and backend/dist/, .env with credentials
Process:
- Load and validate environment configuration
- Validate token format (must start with
ktd_) - Build frontend and backend (calls buildAll)
- Collect files from both dist directories into a structured ZIP
- Create presigned S3 URL via Ketrics API (
POST /tenants/{id}/applications/{id}/deploy) - Upload ZIP buffer to S3 via presigned URL
- Return deployment ID and summary
Outputs: Deployment confirmation with ID, file count, and timing
Special Mode - Dry Run (--dry-run): Shows files to be deployed without uploading
Exit on Error: Config loading failure, token validation, build failure, API error, upload failure
4. Configuration Validation (ketrics validate)
Inputs: Optional paths to ketrics.config.json and .env
Process:
- Check file existence
- Parse JSON and validate against schemas
- Check token format (warning only)
- Collect all errors and warnings
- Report validation results
Outputs: List of errors (blocking) and warnings (informational) Exit on Error: Any validation errors present
5. API Request Execution (ketrics run)
Inputs: JSON configuration file with endpoint, method, headers, body Process:
- Load environment configuration (requires
KETRICS_AUTH_TOKENandKETRICS_RUNTIME_URL) - Parse JSON run file (validates schema)
- Create variable map from environment (tenantId, applicationId, token)
- Interpolate all template variables:
{{tenantId}},{{applicationId}},{{token}} - Construct full URL from runtime URL + interpolated endpoint
- Execute HTTP request with interpolated headers/body
- Display request and response details
Outputs: HTTP response status and body Exit on Error: Missing env vars, invalid JSON, connection refused, timeout
Business Rules
- Token Format: Deployment tokens must start with
ktd_(validated before API calls) - App Name Format: Must start with letter, contain only alphanumeric/hyphens/underscores
- Build Prerequisites: Both frontend and backend must have
node_modulesbefore building - Dist Structure: Frontend builds to
frontend/dist/, backend builds tobackend/dist/ - File Patterns: Include/exclude patterns use glob syntax for flexible file selection
- ZIP Compression: Level 9 compression (maximum) used for all deployments
- Request Timeout: API calls timeout at 30 seconds, S3 uploads at 5 minutes
- Variable Interpolation: All string values in run JSON are scanned for
{{varName}}patterns
Input/Output Expectations
Configuration Files:
ketrics.config.json: JSON with name, version, actions, entry, include/exclude patterns.env: Key=value format with KETRICS_* variables- Run JSON: POST/PUT/DELETE/PATCH/GET requests with endpoint, headers, body
Exit Codes:
0: Successful execution1: Any error condition (validation failure, build failure, API error, etc.)
Technical Details
Technology Stack
- Runtime: Node.js 24.0.0+ (specified in package.json engines)
- Language: TypeScript 5.3.3 with strict type checking
- CLI Framework: Commander.js 12.0.0 (argument parsing and command structure)
- HTTP Client: Axios 1.6.0 (with timeout and error handling)
- Validation: Zod 3.22.4 (schema validation for configs and responses)
- UI/UX:
- Chalk 4.1.2 (colored terminal output)
- Ora 5.4.1 (loading spinners)
- @inquirer/prompts 7.10.1 (interactive prompts)
- File Operations: Native Node.js fs and path modules
- Compression: Archiver 6.0.1 (ZIP creation with streaming)
- Pattern Matching: Glob 10.3.0 (file selection with include/exclude)
- Environment Loading: dotenv 16.3.1 (.env file parsing)
- Process Execution: Native Node.js child_process (execSync for npm commands)
Dependencies Analysis
{
"core-cli": ["[email protected]"],
"validation": ["[email protected]"],
"http": ["[email protected]"],
"compression": ["[email protected]"],
"file-patterns": ["[email protected]"],
"environment": ["[email protected]"],
"ui": ["[email protected]", "[email protected]", "@inquirer/[email protected]"],
"dev-dependencies": ["[email protected]", "[email protected]", "@types/*"]
}File Descriptions
bin/ketrics.ts
- Entry point executable (shebang for direct CLI usage)
- Instantiates CLI via
createCLI()and parses process.argv - Results in
dist/bin/ketrics.jswhich is referenced in package.json bin field
src/cli.ts
- Configures Commander.js program with CLI name, version, and help text
- Defines 5 commands: create, build, deploy, validate, run
- Maps command arguments/options to handler functions
- Exported as
createCLI()function
src/commands/*.ts
- Each file exports single command handler function
- Validates inputs, orchestrates service layer calls
- Handles errors and formats output via logger
- No business logic—purely orchestration and user interaction
src/services/*.ts
- config-service.ts: Zod validation, dotenv parsing, schema enforcement. Functions:
loadEnvConfig(),loadKetricsConfig(),validateConfig() - build-service.ts: npm script execution via child_process. Functions:
buildAll(),runBuild(),validateBuildDirectory(),validateDistDirectory() - api-client.ts: Axios POST to
/tenants/{id}/applications/{id}/deploy. Returns presigned URL and deployment ID. Error handling for 401/403/404 status codes. - zip-service.ts: Archiver for ZIP creation, glob for file collection, streaming compression. Dual functions for config-based and directory-based bundling.
- upload-service.ts: Axios PUT to S3 presigned URL with binary data. 5-minute timeout for large uploads. Error handling for 400/403/413 status codes.
- template-service.ts: Directory traversal to discover templates, recursive copying, JSON field updates. Functions:
getAvailableTemplates(),copyTemplate(),updateAppName()
src/types/index.ts
- Zod schemas for runtime validation:
ketricsConfigSchema,envConfigSchema,runFileSchema,runEnvConfigSchema - TypeScript interfaces derived from schemas via
z.infer<T> - API response types:
DeployResponse(presigned URL data) - Supporting types:
FileInfo,ValidationResult,TemplateInfo
src/utils/logger.ts
- Singleton object with named methods:
info(),success(),warn(),error(),log(),newline(),header(),keyValue(),indent(),file(),box() - Uses chalk for ANSI color codes
- Replaces raw
console.log()throughout codebase
src/utils/spinner.ts
createSpinner(text): Ora spinner instancewithSpinner<T>(text, operation, successText): Wraps async operation with spinner, handles errors, returns result- Provides visual feedback for long-running operations
src/version.ts
- Single auto-generated export:
VERSION = "0.2.3" - Generated by
scripts/generate-version.jsduring build - Referenced in cli.ts for
--versionflag
Configuration Options and Environment Variables
ketrics.config.json Schema (Zod validation):
{
name: string, // Project name (required, min 1 char)
version: string, // Semver format e.g. "1.0.0" (required)
description?: string, // Optional project description
runtime: "nodejs18" | "nodejs20" | "static", // Default: "nodejs18"
actions: string[], // At least 1 action name (required)
entry: string, // Entry point file (required)
include: string[], // Glob patterns to include (required, min 1)
exclude: string[] // Glob patterns to exclude (default: [])
}Environment Variables (loaded from .env):
KETRICS_TOKEN # Deploy token starting with "ktd_" (required)
KETRICS_API_URL # Ketrics API base URL (required, must be valid URL)
KETRICS_TENANT_ID # Tenant UUID (required, UUID format)
KETRICS_APPLICATION_ID # Application UUID (required, UUID format)
KETRICS_AUTH_TOKEN # Runtime auth token (optional, required for run command)
KETRICS_RUNTIME_URL # Runtime API URL (optional, required for run command, must be URL)External Integrations
Ketrics Tenant API
- Endpoint:
POST /tenants/{KETRICS_TENANT_ID}/applications/{KETRICS_APPLICATION_ID}/deploy - Authentication: Bearer token (KETRICS_TOKEN)
- Request: Empty POST body
- Response:
{ success: boolean, data: { uploadUrl, deploymentId, s3Key, expiresAt, expiresInSeconds } } - Errors: 401 (bad token), 403 (no access), 404 (app not found)
AWS S3 (via presigned URL)
- Method: PUT request to presigned URL from deploy response
- Headers:
Content-Type: application/zip,Content-Length: <bytes> - Body: Raw ZIP buffer (binary)
- Timeout: 300 seconds (5 minutes)
- Errors: 400 (expired URL), 403 (URL reused), 413 (file too large)
Ketrics Runtime API (for run command)
- Base URL: KETRICS_RUNTIME_URL from .env
- Endpoint: User-specified path in run JSON
- Authentication: Bearer token (KETRICS_AUTH_TOKEN in Authorization header)
- Methods: GET, POST, PUT, DELETE, PATCH
- Timeout: 30 seconds
- Response: Any JSON/text (no validation)
Data Flow
Deploy Command Data Flow
User Input (--env flag, working directory)
↓
Load .env → dotenv.parse() → Zod validation → EnvConfig object
↓
Build frontend → execSync('npm run build') → frontend/dist/
↓
Build backend → execSync('npm run build') → backend/dist/
↓
Collect files → fs.readdirSync() recursive → FileInfo[] array
↓
Create ZIP → Archiver stream + glob + compression → Buffer
↓
API Call → axios.post() → Ketrics /deploy endpoint → DeployResponse
↓
S3 Upload → axios.put() → presigned URL + ZIP buffer → AWS S3
↓
Result → logger.box() → Deployment ID displayed to userCreate Command Data Flow
User Input (app name, optional --template)
↓
Validate name → Regex check → boolean result
↓
Discover templates → fs.readdirSync(templates/) → TemplateInfo[]
↓
Prompt selection → inquirer.select() → User choice or --template flag
↓
Copy template → Recursive fs.copyFileSync() → New directory tree
↓
Update names → JSON.parse/stringify → Update name field in 3 files
↓
Result → logger.success() → Next steps printed to userRun Command Data Flow
User Input (JSON file path, optional --env flag)
↓
Load .env → dotenv.parse() → EnvConfig validation
↓
Load JSON file → fs.readFileSync() → JSON.parse() → Zod validation → RunFileConfig
↓
Create variables → Map EnvConfig to VariableMap { tenantId, applicationId, token }
↓
Interpolate strings → Regex replace {{varName}} → Fully resolved endpoint/headers/body
↓
Build full URL → KETRICS_RUNTIME_URL + endpoint → Full HTTP URL
↓
HTTP Request → axios() → Method/headers/body from interpolated config → AxiosResponse
↓
Display response → JSON.stringify(response.data) → Pretty-printed to consoleConfiguration Validation Data Flow
User Input (optional --config and --env paths)
↓
Read ketrics.config.json → fs.readFileSync() → JSON.parse() → Zod parse
↓
Collect errors/warnings → Zod error messages + custom checks
↓
Read .env → dotenv.config() → Extract KETRICS_* vars → Zod parse
↓
Token format check → Regex /^ktd_/ → Warning if doesn't match
↓
Return ValidationResult → { valid: boolean, errors: [], warnings: [] }
↓
Display results → logger.error() or logger.success()Error Handling
Error Scenarios and Handling
Configuration Loading Errors
- File not found: "Configuration file not found: {path}\nRun 'ketrics init' to create one."
- Invalid JSON: "Invalid JSON in configuration file: {path}"
- Zod validation: Field-by-field error messages with paths
- Recovery: Exit with code 1, display errors before exit
Build Errors
- Directory missing: "frontend/ directory not found"
- Missing node_modules: "Missing node_modules in {name}/. Run 'cd {name} && npm install' first."
- Build command failure: "{name} build failed. Check the output above for errors."
- Missing dist: "{name} build did not produce dist/ directory"
- Recovery: execSync() inherits stdio (shows npm output), thrown Error caught by command handler
API/Network Errors
- 401 Unauthorized: "Authentication failed: Invalid or expired deployment token.\nPlease check your KETRICS_TOKEN in the .env file."
- 403 Forbidden: "Authorization failed: Token does not have access to this application.\nPlease verify KETRICS_TENANT_ID and KETRICS_APPLICATION_ID."
- 404 Not Found: "Application not found. Please verify KETRICS_APPLICATION_ID."
- Network unreachable: "Network error: Could not connect to {url}\nPlease check your internet connection and KETRICS_API_URL."
- S3 upload 400: "Upload failed: Invalid request. The presigned URL may have expired."
- S3 upload 403: "Upload failed: Access denied. The presigned URL may have expired or been used."
- S3 upload 413: "Upload failed: File too large. Maximum upload size exceeded."
- Recovery: Error message logged, process exit(1)
Input Validation Errors
- Invalid app name: "App name must start with a letter and contain only letters, numbers, hyphens, and underscores"
- Missing template: "Template not found: {name}" with list of available templates
- Directory exists: "Folder '{appName}' already exists."
- Invalid run JSON: "Invalid run file format:" with detailed Zod path and message
- Recovery: Error logged, process exit(1)
Retry Logic
- Explicit Retries: None implemented—all operations are single-attempt
- Presigned URL Expiration: 15 minutes (expiresInSeconds from API response)
- Timeout Handling:
- API calls: 30 second timeout
- S3 uploads: 300 second timeout (5 minutes)
- User can re-run command if timeout occurs
Fallback Mechanisms
- Template Selection: If multiple templates exist, interactive selection via inquirer; if one template exists, auto-select; if none exist, error with instructions
- Build Validation: Checks for node_modules and package.json before running npm build
- Token Format: Validates token format (
ktd_prefix) before API call, providing early feedback - Variable Interpolation: Unknown variables in run JSON remain as-is with warning logged
Logging Approach
Logger Levels (not severity-based, visual categorization):
info(): Blue "ℹ" icon + message (informational)success(): Green "✔" icon + message (operation succeeded)warn(): Yellow "⚠" icon + message (non-blocking issues)error(): Red "✖" icon + message (operation failed)log(): Plain text (neutral output)header(): Bold text with newlines (section markers)keyValue(): Gray key + value (structured data)box(): Green checkmark box (success summary)
Log Points:
- Command start:
logger.header()with command name - Major operation start:
withSpinner()text - Operation completion:
spinner.succeed()text - Data summaries:
logger.keyValue()for important values - Errors:
logger.error()before exit or throw - Success:
logger.box()orlogger.success()at end
Example Deploy Logging:
Ketrics CLI v1.0.0 [header]
ℹ Loading environment... [spinner start]
✔ Loaded environment [spinner succeed]
Building frontend... [info]
Building backend... [info]
✔ Build completed [success]
Frontend dist: ... [keyValue]Usage
Installation and Setup
# Install globally
npm install -g @ketrics/ketrics-cli
# Or use as dev dependency
npm install --save-dev @ketrics/ketrics-cli
# Verify installation
ketrics --versionRunning Commands
Create a New Application
# Interactive template selection
ketrics create my-app
# Specify template directly
ketrics create my-app --template HelloWorldOutput:
- New directory
my-app/with template structure - Console instructions for next steps
- Pre-configured
ketrics.config.jsonand package.json files
Prerequisites: None (discovers templates from bundled templates/)
Build Application
cd my-app
ketrics buildOutput:
- Compiled
frontend/dist/directory - Compiled
backend/dist/directory - Console summary with paths
Prerequisites:
- Current directory contains
frontend/andbackend/subdirectories - Both directories have
node_modules/installed - Both directories have
package.jsonwithbuildscript
Deploy Application
# Standard deployment
ketrics deploy
# Custom .env path
ketrics deploy --env ./config/.env.production
# Dry run (see what would deploy without uploading)
ketrics deploy --dry-runOutput:
- Deployment ID
- File count and total size
- Processing confirmation
Prerequisites:
.envfile with KETRICS_TOKEN, KETRICS_API_URL, KETRICS_TENANT_ID, KETRICS_APPLICATION_ID- Built
frontend/dist/andbackend/dist/directories - Valid deployment token (starts with
ktd_)
Validate Configuration
# Validate with defaults
ketrics validate
# Custom paths
ketrics validate --config ./config/ketrics.config.json --env ./.env.stagingOutput:
- List of errors (if any)
- List of warnings (if any)
- Success/failure status
Prerequisites: None (creates validation report even if files don't exist)
Execute API Requests
# Create request file: request.json
{
"endpoint": "/users/{{tenantId}}/profile",
"method": "GET",
"headers": {
"Authorization": "Bearer {{token}}"
}
}
# Execute request
ketrics run request.json
# Verbose output
ketrics run request.json --verbose
# Custom .env
ketrics run request.json --env ./.env.devOutput:
- Formatted HTTP request (method, URL, headers, body)
- Formatted HTTP response (status, body)
- Duration in seconds
Prerequisites:
.envfile with KETRICS_AUTH_TOKEN and KETRICS_RUNTIME_URL- Valid JSON request file
Example Invocations
Full Deployment Workflow:
# Create new project
ketrics create my-todo-app --template HelloWorld
# Navigate to project
cd my-todo-app
# Install dependencies
cd frontend && npm install
cd ../backend && npm install
cd ..
# Copy .env from template
cp .env.example .env
# Edit .env with your credentials
# Validate configuration
ketrics validate
# Build application
ketrics build
# Deploy to Ketrics
ketrics deployTesting API Endpoints:
# Create .env with runtime credentials
cat > .env.test << EOF
KETRICS_TENANT_ID=12345678-1234-1234-1234-123456789012
KETRICS_APPLICATION_ID=87654321-4321-4321-4321-210987654321
KETRICS_AUTH_TOKEN=your_runtime_token_here
KETRICS_RUNTIME_URL=https://api.runtime.ketrics.io
EOF
# Create request file
cat > api-test.json << EOF
{
"endpoint": "/health",
"method": "GET",
"headers": {
"Authorization": "Bearer {{token}}"
}
}
EOF
# Execute
ketrics run api-test.json --env .env.testTesting Approach
Unit Testing (not included in code):
- Would test individual service functions:
loadEnvConfig(),buildAll(),collectFiles(), etc. - Mock file system, axios, child_process
- Verify schema validation with valid/invalid inputs
- Test error handling paths
Integration Testing (not included in code):
- Test complete command workflows
- Use temporary directories and files
- Mock Ketrics API responses
- Verify file structure creation and modification
Manual Testing (recommended):
- Create test project with
ketrics create test-app - Modify
.envwith test credentials - Run
ketrics validateto verify setup - Run
ketrics buildto verify npm scripts exist - Run
ketrics deploy --dry-runto verify packaging - Run
ketrics runwith test request to verify runtime access - Full
ketrics deployto staging environment
Testing Checklist:
- Create command with interactive and flag-based template selection
- Build command with missing node_modules, missing dist directories
- Deploy command with invalid token format, network errors, S3 failures
- Validate command with missing files, invalid JSON, schema violations
- Run command with missing variables, malformed JSON, API errors
- Edge cases: empty directories, very large files, special characters in names
Advanced Topics
Custom Configuration Patterns
The include/exclude patterns in ketrics.config.json use glob syntax:
{
"include": [
"frontend/dist/**/*",
"backend/dist/**/*"
],
"exclude": [
"**/*.map",
"**/node_modules/**",
"**/.git/**"
]
}Programmatic Usage
The CLI exports services for use in other Node.js applications:
import {
loadEnvConfig,
buildAll,
createDeploymentZipBundle,
uploadToS3,
initiateDeploy
} from '@ketrics/ketrics-cli';
// Load config
const config = loadEnvConfig('/path/to/.env');
// Build application
const buildResult = buildAll(process.cwd());
// Create ZIP
const zip = await createDeploymentZipBundle(
buildResult.frontendDistPath,
buildResult.backendDistPath
);
// Upload
await uploadToS3(presignedUrl, zip.buffer);Environment-Specific Deployments
Use different .env files for different environments:
# Staging
ketrics deploy --env .env.staging
# Production
ketrics deploy --env .env.productionDebugging
Enable verbose output where available:
# Run command with verbose flag
ketrics run request.json --verbose
# Build process inherits stdio (shows npm output)
ketrics build # Shows all npm build output
# API client logs URL before request
# (Search for "console.log" in api-client.ts for debug points)Version Information
- CLI Version: 0.2.3 (auto-generated in
src/version.ts) - Node.js Requirement: 24.0.0 or later
- TypeScript: 5.3.3
- Last Updated: 2024-2025
Contributing
When modifying the CLI:
- Follow TypeScript strict mode (tsconfig.json)
- Export types and services from
src/index.ts - Add Zod schemas for new configuration options
- Use logger utility instead of console.log
- Wrap async operations with withSpinner for UX
- Run
npm run buildbefore testing (generates version.ts) - Test all command paths, especially error scenarios
