Skip to content

Template Reference

Nagare uses the Vento template engine for generating version files and processing custom templates. Templates have access to comprehensive data about the release, project, and environment.

export const VERSION = "{{ version }}";
export const BUILD_INFO = {
date: "{{ buildDate }}",
commit: "{{ gitCommit }}"
};

Templates in Nagare use Vento syntax, which provides a secure and powerful templating system with auto-escaping, custom filters, and conditional logic. Templates can generate TypeScript, JSON, YAML, or any custom format needed for version tracking.

Syntax: {{ variable }}
Description: Output a variable value with auto-escaping

Variables are automatically escaped for security. In code generation contexts, use the safe filter to output raw values.

Example:

// String values are output as-is
export const VERSION = "{{ version }}";
// Numbers need the safe filter
export const MAJOR = {{ versionComponents.major |> safe }};

Syntax: {{ value |> filterName }}
Description: Transform values using filters

IMPORTANT: Vento uses |> (F# pipeline syntax), NOT single pipe |.

Built-in filters:

  • safe - Output raw value without escaping
  • escape - Force HTML escaping (for HTML contexts)
  • jsonStringify - Convert to JSON with optional indentation
  • formatDate - Format date to ISO date string
  • shortHash - Truncate git hash to specified length
  • safeString - Escape quotes for JSON embedding

Examples:

// JSON stringify an object
export const METADATA = {{ metadata |> jsonStringify |> safe }};
// Format a date
export const RELEASE_DATE = "{{ buildDate |> formatDate }}";
// Short git hash
export const SHORT_COMMIT = "{{ gitCommit |> shortHash(7) }}";
// Chain filters
export const DATA = {{ releaseNotes |> jsonStringify(2) |> safe }};

Syntax: {{ if condition }} ... {{ /if }}
Description: Conditional rendering

Examples:

{{- if project.author }}
author: "{{ project.author }}",
{{- /if }}
{{- if metadata }}
export const METADATA = {{ metadata |> jsonStringify |> safe }};
{{- else }}
export const METADATA = {};
{{- /if }}
// Check specific properties
{{- if versionComponents.prerelease }}
export const PRERELEASE = "{{ versionComponents.prerelease }}";
{{- /if }}

Syntax: {{- and -}}
Description: Remove whitespace before/after tags

  • {{- removes all whitespace before the tag (including newlines)
  • -}} removes all whitespace after the tag
  • Use carefully to avoid unintended formatting issues

Example:

// Without whitespace control
{{ if value }}
key: "value"
{{ /if }}
// With whitespace control (removes blank lines)
{{- if value }}
key: "value"
{{- /if }}

Syntax: {{# comment text #}}
Description: Template comments (not output)

Example:

{{# This comment won't appear in output #}}
export const VERSION = "{{ version }}";
VariableTypeDescriptionExample
versionstringFull version string"1.2.3"
buildDatestringISO timestamp"2024-01-15T10:30:00Z"
gitCommitstringFull git commit hash"abc123def456..."
environmentstringBuild environment"production"

Object: versionComponents
Description: Parsed semantic version parts

PropertyTypeDescriptionExample
majornumberMajor version1
minornumberMinor version2
patchnumberPatch version3
prereleasestring|nullPre-release identifier"beta.1"

Example usage:

export const VERSION_INFO = {
major: {{ versionComponents.major |> safe }},
minor: {{ versionComponents.minor |> safe }},
patch: {{ versionComponents.patch |> safe }},
prerelease: {{ if versionComponents.prerelease }}{{ versionComponents.prerelease |> jsonStringify |> safe }}{{ else }}null{{ /if }}
} as const;

Object: project
Description: Project metadata from configuration

PropertyTypeDescription
namestringProject name
descriptionstring|undefinedProject description
repositorystringRepository URL
homepagestring|undefinedProject homepage
licensestring|undefinedLicense identifier
authorstring|undefinedAuthor information

Example usage:

export const APP_INFO = {
name: "{{ project.name }}",
{{- if project.description }}
description: "{{ project.description }}",
{{- /if }}
repository: "{{ project.repository }}"
} as const;

Object: releaseNotes
Description: Changelog entries for current release

PropertyTypeDescription
versionstringRelease version
datestringRelease date
addedstring[]New features
changedstring[]Changes/improvements
deprecatedstring[]Deprecations
removedstring[]Removed features
fixedstring[]Bug fixes
securitystring[]Security updates

Example usage:

{{- if releaseNotes }}
export const CHANGELOG = {
version: "{{ releaseNotes.version }}",
date: "{{ releaseNotes.date }}",
{{- if releaseNotes.added.length > 0 }}
added: {{ releaseNotes.added |> jsonStringify |> safe }},
{{- /if }}
{{- if releaseNotes.fixed.length > 0 }}
fixed: {{ releaseNotes.fixed |> jsonStringify |> safe }}
{{- /if }}
} as const;
{{- /if }}

Object: metadata
Description: Custom metadata from configuration and data providers

Metadata is merged from:

  1. releaseNotes.metadata in configuration
  2. Template data providers
  3. Direct metadata properties

Example configuration:

releaseNotes: {
metadata: {
apiEndpoints: ['/api/v1', '/health'],
features: ['auth', 'websocket']
}
}

Example usage:

{{# Metadata is available as an object #}}
{{- if metadata }}
export const APP_METADATA = {{ metadata |> jsonStringify |> safe }};
{{- /if }}
{{# Individual properties are also at root level #}}
{{- if apiEndpoints }}
export const API_ENDPOINTS = {{ apiEndpoints |> jsonStringify |> safe }};
{{- /if }}
VariableTypeDescriptionExample
currentYearnumberCurrent year2024
buildDateFormattedstringFormatted date"2024-01-15"
shortCommitstringShort git hash"abc123d"

TypeScript Template {#TypeScript-template}

Section titled “TypeScript Template {#TypeScript-template}”

File: templates/typescript.vto
Usage: template: 'typescript'

Generates a TypeScript module with const exports:

export const VERSION = "1.2.3";
export const BUILD_INFO = {
buildDate: "2024-01-15T10:30:00Z",
gitCommit: "abc123def456",
buildEnvironment: "production",
versionComponents: {
major: 1,
minor: 2,
patch: 3,
prerelease: null,
},
} as const;
// ... additional exports

File: templates/json.vto
Usage: template: 'json'

Generates a JSON file:

{
"version": "1.2.3",
"buildDate": "2024-01-15T10:30:00Z",
"gitCommit": "abc123def456",
"project": {
"name": "My App",
"repository": "https://github.com/user/app"
}
}

File: templates/yaml.vto
Usage: template: 'yaml'

Generates a YAML file:

version: 1.2.3
buildDate: 2024-01-15T10:30:00Z
gitCommit: abc123def456
project:
name: My App
repository: https://github.com/user/app
versionFile: {
path: './version.js',
template: 'custom',
customTemplate: `
export const VERSION = "{{ version }}";
export const BUILD_TIME = {{ Date.now() |> safe }};
`
}

Advanced Custom Template {#custom-advanced}

Section titled “Advanced Custom Template {#custom-advanced}”
versionFile: {
path: './src/build-info.ts',
template: 'custom',
customTemplate: `
/**
* Build information for {{ project.name }}
* Generated on {{ buildDate |> formatDate }}
*/
export interface BuildInfo {
version: string;
major: number;
minor: number;
patch: number;
commit: string;
date: string;
{{- if metadata.features }}
features: string[];
{{- /if }}
}
export const BUILD: BuildInfo = {
version: "{{ version }}",
major: {{ versionComponents.major |> safe }},
minor: {{ versionComponents.minor |> safe }},
patch: {{ versionComponents.patch |> safe }},
commit: "{{ gitCommit }}",
date: "{{ buildDate }}",
{{- if metadata.features }}
features: {{ metadata.features |> jsonStringify |> safe }}
{{- /if }}
};
{{- if releaseNotes.added.length > 0 }}
export const NEW_FEATURES = {{ releaseNotes.added |> jsonStringify |> safe }};
{{- /if }}
`
}

Nagare implements template sandboxing with three levels:

  1. strict (default): Blocks all potentially dangerous operations
  2. moderate: Allows some safe operations with restrictions
  3. disabled: No sandboxing (use only with trusted templates)

Blocked patterns in strict mode:

  • File system access (Deno.readFile, import(), etc.)
  • Network access (fetch, XMLHttpRequest)
  • Process execution (Deno.Command, Deno.run)
  • Global object access (globalThis, window)
  • JavaScript execution (eval, Function)

For code generation (TypeScript, JavaScript, JSON):

// Use |> safe for raw output
export const DATA = {{ data |> jsonStringify |> safe }};

For HTML contexts (if generating HTML):

// Always escape for HTML attributes
<div data-version="{{ version |> escape }}">
templates: {
dataProviders: {
buildMetrics: async () => ({
bundleSize: await calculateBundleSize(),
testCount: await getTestCount()
}),
gitInfo: async () => ({
branch: await getCurrentBranch(),
contributors: await getContributorCount()
})
}
}
{{# Data from providers is merged into template context #}}
{{- if buildMetrics }}
export const BUILD_METRICS = {
bundleSize: {{ buildMetrics.bundleSize |> safe }},
testCount: {{ buildMetrics.testCount |> safe }}
};
{{- /if }}
{{# Individual properties available at root #}}
{{- if bundleSize }}
export const BUNDLE_SIZE = {{ bundleSize |> safe }};
{{- /if }}

Conditional Exports {#conditional-exports}

Section titled “Conditional Exports {#conditional-exports}”
{{# Only export if data exists #}}
{{- if metadata.apiEndpoints }}
export const API_ENDPOINTS = {{ metadata.apiEndpoints |> jsonStringify |> safe }};
{{- /if }}
{{- if project.license }}
export const LICENSE = "{{ project.license }}";
{{- /if }}
{{# Generate TypeScript with proper types #}}
export interface VersionInfo {
version: string;
components: {
major: number;
minor: number;
patch: number;
prerelease: string | null;
};
}
export const VERSION_INFO: VersionInfo = {
version: "{{ version }}",
components: {
major: {{ versionComponents.major |> safe }},
minor: {{ versionComponents.minor |> safe }},
patch: {{ versionComponents.patch |> safe }},
prerelease: {{ versionComponents.prerelease |> jsonStringify |> safe }}
}
};
{{# Adapt output based on file extension #}}
{{- if path.endsWith('.json') }}
{
"version": "{{ version }}",
"build": {{ buildInfo |> jsonStringify |> safe }}
}
{{- else if path.endsWith('.yaml') }}
version: {{ version }}
build:
date: {{ buildDate }}
commit: {{ gitCommit }}
{{- else }}
export const VERSION = "{{ version }}";
{{- /if }}

Error: “Template processing failed”
Cause: Invalid Vento syntax
Solution: Check for:

  • Using | instead of |> for filters
  • Unclosed tags ({{ if }} without {{ /if }})
  • Undefined variables or properties

Error: “Template security violation”
Cause: Template contains blocked patterns
Solution: Remove dangerous operations or set templateSandbox: 'disabled' (not recommended)

Error: “Cannot read property of undefined”
Cause: Accessing nested property that doesn’t exist
Solution: Use conditional checks:

{{- if metadata && metadata.features }}
features: {{ metadata.features |> jsonStringify |> safe }}
{{- /if }}