CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-finos--calm-cli

A comprehensive command-line interface for working with the Common Architecture Language Model (CALM)

Overview
Eval results
Files

template-command.mddocs/

Template Command

NOTE: This is a CLI-only command. @finos/calm-cli does not export functions for programmatic use.

The template command generates files from a CALM model using Handlebars templates. It supports template bundles, single template files, or directories of templates, enabling code generation, configuration file creation, and custom output formats from CALM architectures.

Capabilities

Template Command

Generate files from a CALM model using templates.

/**
 * Generate files from a CALM model using a template bundle, single file, or directory
 * @command calm template [options]
 */
interface TemplateCommandOptions {
  /** Path to CALM architecture JSON file
   * CLI flags: -a, --architecture <file>
   * Required: yes
   */
  architecture: string;

  /** Path to output directory or file
   * CLI flags: -o, --output <file>
   * Required: yes
   */
  output: string;

  /** Delete output directory contents before processing
   * CLI flags: --clear-output-directory
   * Default: false
   */
  clearOutputDirectory?: boolean;

  /** Path to template bundle directory
   * CLI flags: -b, --bundle <path>
   */
  bundle?: string;

  /** Path to single .hbs or .md template file
   * CLI flags: -t, --template <path>
   */
  template?: string;

  /** Path to directory of .hbs/.md templates
   * CLI flags: -d, --template-dir <path>
   */
  templateDir?: string;

  /** Path to JSON file mapping URLs to local file paths
   * CLI flags: -u, --url-to-local-file-mapping <path>
   */
  urlToLocalFileMapping?: string;

  /** Enable verbose logging
   * CLI flags: -v, --verbose
   * Default: false
   */
  verbose?: boolean;
}

Requirements:

  • Exactly one of bundle, template, or templateDir must be specified
  • Cannot use multiple template source options simultaneously

Usage Examples:

# Using a template bundle
calm template -a architecture.json -b ./template-bundle -o ./output

# Using a single template file
calm template -a architecture.json -t ./template.hbs -o ./output.txt

# Using a directory of templates
calm template -a architecture.json -d ./templates -o ./output

# Clear output directory before generation
calm template -a architecture.json -b ./bundle -o ./output --clear-output-directory

# With URL-to-local-file mapping
calm template -a architecture.json -b ./bundle -o ./output -u ./url-mappings.json

# With verbose logging
calm template -a architecture.json -b ./bundle -o ./output -v

Template Types

Template Bundle

A template bundle is a directory containing:

  • index.json: Bundle configuration defining template structure
  • Handlebars template files (.hbs)
  • Supporting files and resources
  • Optional transformer implementation

Bundle Structure Example:

template-bundle/
├── index.json
├── main.hbs
├── partials/
│   ├── header.hbs
│   └── footer.hbs
└── helpers/
    └── custom-helpers.js

Usage:

calm template -a architecture.json -b ./template-bundle -o ./output

Single Template File

A single Handlebars or Markdown template file for simple transformations.

Usage:

# Handlebars template
calm template -a architecture.json -t ./template.hbs -o ./output.html

# Markdown template
calm template -a architecture.json -t ./template.md -o ./output.md

Template Directory

A directory containing multiple template files, each processed independently.

Directory Structure Example:

templates/
├── api.hbs
├── database.hbs
├── frontend.hbs
└── README.md.hbs

Usage:

calm template -a architecture.json -d ./templates -o ./output

Each template file generates a corresponding output file with the same name (minus .hbs extension).

Handlebars Templates

Templates use Handlebars syntax with access to the CALM architecture model.

Template Variables

Templates have access to the complete CALM architecture:

{{!-- Access nodes --}}
{{#each nodes}}
  Node: {{this.name}}
  Type: {{this.node-type}}
  ID: {{this.unique-id}}
{{/each}}

{{!-- Access relationships --}}
{{#each relationships}}
  From: {{this.relationship-type.connects.source.node}}
  To: {{this.relationship-type.connects.destination.node}}
{{/each}}

{{!-- Access metadata --}}
Schema: {{$schema}}

Built-in Helpers

Handlebars provides standard helpers:

  • {{#each}} - Iterate over arrays
  • {{#if}} - Conditional rendering
  • {{#unless}} - Negative conditional
  • {{#with}} - Change context

Custom Helpers

Template bundles can provide custom helpers for specialized transformations.

URL-to-Local-File Mapping

When CALM models reference external URLs (e.g., for flows or patterns), you can map these to local files for offline processing.

Mapping File Format

{
  "https://calm.finos.org/docuflow/flow/document-upload": "flows/flow-document-upload.json",
  "https://calm.finos.org/patterns/api-gateway": "patterns/api-gateway.json"
}

Path Resolution:

  • Paths are relative to the mapping file's directory
  • Absolute paths are also supported

Usage

calm template \
  -a architecture.json \
  -b ./template-bundle \
  -o ./output \
  -u ./url-mappings.json

When the template processor encounters a URL reference in the architecture, it will load the content from the mapped local file instead of fetching from the URL.

Output Behavior

Default Behavior

  • Output directory is created if it doesn't exist
  • Existing files are modified if they match template output names
  • Unrelated files in output directory remain unchanged

Clear Output Directory

With --clear-output-directory flag:

calm template -a architecture.json -b ./bundle -o ./output --clear-output-directory

Warning: This completely deletes all files and subdirectories in the output directory before generation. Use with caution!

Template Processing Modes

The CLI uses different processing modes from @finos/calm-shared:

Bundle Mode

mode: 'bundle'
templatePath: './template-bundle'

Processes a complete template bundle with configuration.

Template Mode

mode: 'template'
templatePath: './template.hbs'

Processes a single template file.

Template Directory Mode

mode: 'template-directory'
templatePath: './templates'

Processes all templates in a directory.

Common Use Cases

Code Generation

Generate source code from CALM architectures:

{{!-- api.hbs --}}
// Generated API interfaces from CALM architecture

{{#each nodes}}
{{#if (eq this.node-type "service")}}
export interface {{this.name}}Service {
  {{#each this.interfaces}}
  // {{this.protocol}} interface on {{this.host}}:{{this.port}}
  {{/each}}
}
{{/if}}
{{/each}}

Configuration Files

Generate configuration files for deployment:

{{!-- docker-compose.yml.hbs --}}
version: '3.8'
services:
  {{#each nodes}}
  {{this.unique-id}}:
    image: {{this.name}}:latest
    ports:
      {{#each this.interfaces}}
      - "{{this.port}}:{{this.port}}"
      {{/each}}
  {{/each}}

Documentation

Generate architecture documentation:

{{!-- README.md.hbs --}}
# Architecture Documentation

## Services

{{#each nodes}}
### {{this.name}}

- **Type:** {{this.node-type}}
- **ID:** {{this.unique-id}}
{{#if this.description}}
- **Description:** {{this.description}}
{{/if}}

#### Interfaces
{{#each this.interfaces}}
- {{this.protocol}} on {{this.host}}:{{this.port}}
{{/each}}
{{/each}}

Infrastructure as Code

Generate Terraform or CloudFormation templates:

{{!-- main.tf.hbs --}}
{{#each nodes}}
{{#if (eq this.node-type "database")}}
resource "aws_db_instance" "{{this.unique-id}}" {
  identifier = "{{this.unique-id}}"
  engine     = "{{this.metadata.engine}}"
  {{#each this.interfaces}}
  port       = {{this.port}}
  {{/each}}
}
{{/if}}
{{/each}}

Error Handling

Common Errors

Multiple Template Options:

❌ Please specify exactly one of --template, --template-dir, or --bundle

Solution: Use only one template source option.

Missing Required Options:

error: required option '-a, --architecture <path>' not specified

Solution: Provide required architecture and output options.

Architecture File Not Found:

Error: ENOENT: no such file or directory

Solution: Verify architecture file path is correct.

Template Not Found:

Error: Template file not found

Solution: Verify template path is correct and file exists.

Invalid URL Mapping File:

Error reading url to local file mapping file

Solution: Verify mapping file is valid JSON with correct format.

Template Syntax Error:

Error: Parse error on line X

Solution: Check Handlebars template syntax for errors.

Integration with Other Commands

Template generation is typically used after architecture creation and validation:

# Step 1: Generate architecture from pattern
calm generate -p pattern.json -o architecture.json

# Step 2: Edit and validate architecture
calm validate -a architecture.json -p pattern.json

# Step 3: Generate code/configuration from architecture
calm template -a architecture.json -b ./code-gen-bundle -o ./src

# Step 4: Use generated code in project
npm install
npm run build

Advanced Examples

Multi-Output Bundle

Create a template bundle that generates multiple files:

index.json:

{
  "name": "microservices-generator",
  "version": "1.0.0",
  "templates": [
    {
      "input": "service.hbs",
      "output": "src/services/{{unique-id}}.ts"
    },
    {
      "input": "dockerfile.hbs",
      "output": "docker/{{unique-id}}/Dockerfile"
    }
  ]
}

Conditional Generation

Use conditionals to generate different outputs based on architecture content:

{{#each nodes}}
{{#if (eq this.node-type "database")}}
  {{> database-config this}}
{{else if (eq this.node-type "service")}}
  {{> service-config this}}
{{else}}
  {{> default-config this}}
{{/if}}
{{/each}}

Custom Transformers

Template bundles can include custom transformers to pre-process the CALM model:

// transformer.ts
export class CustomTransformer {
  transform(architecture: any): any {
    // Transform architecture structure for templates
    return {
      ...architecture,
      serviceNodes: architecture.nodes.filter(n => n['node-type'] === 'service'),
      databaseNodes: architecture.nodes.filter(n => n['node-type'] === 'database')
    };
  }
}

Performance Considerations

Large Architectures

For architectures with many nodes/relationships:

  • Use template fragments and partials
  • Avoid nested loops where possible
  • Consider pre-filtering data in transformers

Output Directory

  • Use --clear-output-directory for clean slate generation
  • Without flag, only modified files are updated (faster for incremental changes)

Caching

The TemplateProcessor from @finos/calm-shared may cache:

  • Parsed templates
  • Loaded architecture
  • URL mappings

Subsequent runs with same inputs are faster.

Debugging

Verbose Mode

Enable verbose logging to debug template processing:

calm template -a architecture.json -b ./bundle -o ./output -v

Shows:

  • Template loading
  • Architecture parsing
  • URL mapping resolution
  • File writing operations

Template Testing

Test templates with minimal architectures:

{
  "$schema": "https://calm.finos.org/schemas/calm-v1.json",
  "nodes": [
    {
      "unique-id": "test-node",
      "node-type": "service",
      "name": "Test Service"
    }
  ]
}

Output Inspection

Review generated files to verify template logic:

calm template -a test-arch.json -t test-template.hbs -o test-output.txt
cat test-output.txt

Install with Tessl CLI

npx tessl i tessl/npm-finos--calm-cli

docs

copilot-chatmode-command.md

docify-command.md

generate-command.md

index.md

server-command.md

template-command.md

validate-command.md

tile.json