A comprehensive command-line interface for working with the Common Architecture Language Model (CALM)
NOTE: This is a CLI-only command. @finos/calm-cli does not export functions for programmatic use.
The server command starts an HTTP server providing REST API access to CALM validation operations. This experimental feature enables programmatic validation through HTTP requests, useful for integrating CALM validation into web applications, microservices, or CI/CD pipelines.
Start an HTTP server to provide REST API access to validation operations.
/**
* Start a HTTP server to proxy CLI commands (experimental)
* @command calm server [options]
*/
interface ServerCommandOptions {
/** Server port
* CLI flags: --port <port>
* Default: "3000"
*/
port?: string;
/** Path to directory containing meta schemas
* CLI flags: -s, --schema-directory <path>
* Required: yes
*/
schemaDirectory: string;
/** Enable verbose logging
* CLI flags: -v, --verbose
* Default: false
*/
verbose?: boolean;
}Usage Examples:
# Start server on default port 3000
calm server -s ./calm/schemas
# Start server on custom port
calm server --port 8080 -s ./calm/schemas
# Start with verbose logging
calm server --port 3000 -s ./calm/schemas -vCheck server health status.
/**
* GET /health
* Health check endpoint
* @returns StatusResponse with status "OK"
*/
interface HealthCheckEndpoint {
method: 'GET';
path: '/health';
response: StatusResponse;
}
interface StatusResponse {
status: string; // "OK"
}Example Request:
curl http://localhost:3000/healthExample Response:
{
"status": "OK"
}Validate a CALM architecture against its embedded schema.
/**
* POST /calm/validate
* Validate CALM architecture
* @rateLimit 100 requests per 15 minutes per IP
* @returns ValidationOutcome on success or ErrorResponse on failure
*/
interface ValidateEndpoint {
method: 'POST';
path: '/calm/validate';
headers: {
'Content-Type': 'application/json';
};
body: ValidationRequest;
response: ValidationOutcome | ErrorResponse;
statusCodes: {
201: 'Validation completed successfully';
400: 'Invalid request (missing $schema, invalid JSON)';
429: 'Rate limit exceeded';
500: 'Server error (schema loading failed, validation error)';
};
}
interface ValidationRequest {
/** JSON string containing CALM architecture */
architecture: string;
}
interface ErrorResponse {
error: string;
}Example Request:
curl -X POST http://localhost:3000/calm/validate \
-H "Content-Type: application/json" \
-d '{
"architecture": "{\"$schema\":\"https://calm.finos.org/schemas/calm-v1.json\",\"nodes\":[]}"
}'Example Success Response (201):
{
"jsonSchemaValidationOutputs": [],
"spectralSchemaValidationOutputs": [],
"hasErrors": false,
"hasWarnings": false
}Example Error Response (400):
{
"error": "The \"$schema\" field is missing from the request body"
}Example Error Response (429):
{
"error": "Too many requests, please try again later."
}The server command uses CALMHub URL from the user configuration file for remote pattern and schema loading:
Via User Configuration File (~/.calm.json):
{
"calmHubUrl": "https://calmhub.example.com"
}Important Distinction from Generate Command:
Unlike the generate command which accepts both a -c, --calm-hub-url command-line option and configuration file setting, the server command does NOT accept --calm-hub-url as a command-line option. The server will only use the CALMHub URL from the ~/.calm.json configuration file if present.
Rationale: The server needs a consistent configuration that doesn't change per-request. Since the server runs continuously and handles multiple validation requests, having a stable, file-based configuration is more appropriate than per-invocation command-line options.
To configure CALMHub for the server:
~/.calm.json in your home directorycalmHubUrl property with your CALMHub instance URLThe validation endpoint includes rate limiting to prevent abuse:
/**
* Express router configuration for all server routes
*/
class CLIServerRoutes {
router: Router;
/**
* @param schemaDirectory - SchemaDirectory instance for validation
* @param debug - Enable debug logging (default: false)
*/
constructor(schemaDirectory: SchemaDirectory, debug?: boolean);
}
/**
* Express router for validation API endpoint
* Includes rate limiting and error handling
*/
class ValidationRouter {
/**
* @param router - Express Router instance
* @param schemaDirectory - SchemaDirectory instance for validation
* @param debug - Enable debug logging (default: false)
*/
constructor(
router: Router,
schemaDirectory: SchemaDirectory,
debug?: boolean
);
}
/**
* Express router for health check endpoint
*/
class HealthRouter {
/**
* @param router - Express Router instance
*/
constructor(router: Router);
}/calm/validate$schema field from architectureMissing $schema Field:
{
"error": "The \"$schema\" field is missing from the request body"
}Invalid JSON:
{
"error": "Invalid JSON format for architecture"
}Schema Not Available:
{
"error": "The \"$schema\" field referenced is not available to the server"
}Validation Failed:
{
"error": "Validation error message"
}import axios from 'axios';
async function validateArchitecture(architecture: object) {
try {
const response = await axios.post('http://localhost:3000/calm/validate', {
architecture: JSON.stringify(architecture)
});
console.log('Validation result:', response.data);
return response.data;
} catch (error) {
if (error.response) {
console.error('Validation failed:', error.response.data.error);
} else {
console.error('Request failed:', error.message);
}
throw error;
}
}
// Usage
const myArchitecture = {
"$schema": "https://calm.finos.org/schemas/calm-v1.json",
"nodes": [
{
"unique-id": "api-gateway",
"node-type": "system",
"name": "API Gateway"
}
]
};
await validateArchitecture(myArchitecture);import requests
import json
def validate_architecture(architecture):
url = 'http://localhost:3000/calm/validate'
headers = {'Content-Type': 'application/json'}
payload = {
'architecture': json.dumps(architecture)
}
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 201:
return response.json()
else:
raise Exception(f"Validation failed: {response.json()['error']}")
# Usage
my_architecture = {
"$schema": "https://calm.finos.org/schemas/calm-v1.json",
"nodes": []
}
result = validate_architecture(my_architecture)
print("Validation result:", result)# Valid architecture
curl -X POST http://localhost:3000/calm/validate \
-H "Content-Type: application/json" \
-d @- << 'EOF'
{
"architecture": "{\"$schema\":\"https://calm.finos.org/schemas/calm-v1.json\",\"nodes\":[]}"
}
EOF
# Architecture with validation errors
curl -X POST http://localhost:3000/calm/validate \
-H "Content-Type: application/json" \
-d '{"architecture": "{\"nodes\":[]}"}'
# Health check
curl http://localhost:3000/healthThe server requires a schema directory containing CALM meta schemas:
calm server -s ./calm/releaseThe schema directory should contain:
Default port is 3000, but can be customized:
calm server --port 8080 -s ./schemasImportant: Ensure the port is not already in use by another application.
Enable verbose logging for debugging:
calm server --port 3000 -s ./schemas -vVerbose mode logs:
For production use, consider:
Example Dockerfile:
FROM node:18-alpine
WORKDIR /app
# Install CALM CLI
RUN npm install -g @finos/calm-cli
# Copy schemas
COPY ./schemas /app/schemas
# Expose port
EXPOSE 3000
# Start server
CMD ["calm", "server", "--port", "3000", "-s", "/app/schemas"]Example Kubernetes manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: calm-server
spec:
replicas: 3
selector:
matchLabels:
app: calm-server
template:
metadata:
labels:
app: calm-server
spec:
containers:
- name: calm-server
image: calm-server:latest
ports:
- containerPort: 3000
env:
- name: PORT
value: "3000"
---
apiVersion: v1
kind: Service
metadata:
name: calm-server
spec:
selector:
app: calm-server
ports:
- port: 80
targetPort: 3000
type: LoadBalancerExperimental Feature: The server command is marked as experimental and may have limitations:
$schema, not separate pattern filesUse Cases:
Not Recommended For:
Port Already in Use:
Error: listen EADDRINUSE: address already in use :::3000Solution: Use a different port or stop the conflicting process.
Schema Directory Not Found:
Error: ENOENT: no such file or directorySolution: Verify schema directory path is correct.
Permission Denied:
Error: listen EACCES: permission deniedSolution: Use a port number > 1024 or run with appropriate permissions.
All runtime errors are caught and returned as ErrorResponse with appropriate HTTP status codes. The server remains running and available for subsequent requests.
Use the /health endpoint for uptime monitoring:
# Simple health check
curl -f http://localhost:3000/health || echo "Server down"
# With monitoring tool
watch -n 30 'curl -s http://localhost:3000/health | jq .status'The server logs important events:
Access logs through the application's stdout/stderr.
Install with Tessl CLI
npx tessl i tessl/npm-finos--calm-cli