Skip to content

Commit 60e0953

Browse files
bordeuxclaude
andcommitted
docs: add debugging & development functions documentation
- Document all 6 debugging functions (debug, type_of, inspect, assert, warn, abort) - Add comprehensive examples and use cases for each function - Include practical configuration validation examples - Add debugging capabilities to features list - Update table of contents with new section 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 8cd5831 commit 60e0953

1 file changed

Lines changed: 266 additions & 0 deletions

File tree

README.md

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ A fast and simple command-line template rendering tool using [MiniJinja](https:/
2727
- [Path Manipulation Functions](#path-manipulation-functions)
2828
- [Data Parsing Functions](#data-parsing-functions)
2929
- [Validation Functions](#validation-functions)
30+
- [Debugging & Development Functions](#debugging--development-functions)
3031
- [Advanced Examples](#advanced-examples)
3132
- [Error Handling](#error-handling)
3233
- [Development](#development)
@@ -75,6 +76,7 @@ tmpltool greeting.tmpl
7576
- **Data Parsing**: Parse and read JSON, YAML, TOML files
7677
- **Validation**: Validate emails, URLs, IPs, UUIDs, regex matching
7778
- **System & Network**: Get hostname, username, directories, IP addresses, DNS resolution, port availability
79+
- **Debugging & Development**: Debug output, type checking, assertions, warnings, error handling
7880
- **String Filters**: 12+ filters for case conversion, indentation, padding, quoting, and more
7981
- **Security**: Built-in protections with optional `--trust` mode
8082
- **Flexible I/O**: File or stdin input, file or stdout output
@@ -2117,6 +2119,270 @@ Correlation ID: {{ correlation_id }}
21172119
{% endif %}
21182120
```
21192121
2122+
### Debugging & Development Functions
2123+
2124+
Functions for debugging templates, validating data, and controlling template execution flow during development and production.
2125+
2126+
#### `debug(value)`
2127+
2128+
Print a value to stderr and return it unchanged. Useful for inspecting values during template development.
2129+
2130+
**Arguments:**
2131+
- `value` (required) - Value to debug
2132+
2133+
**Returns:** The same value (allows chaining)
2134+
2135+
**Examples:**
2136+
```jinja
2137+
{# Debug a variable #}
2138+
{% set config = debug(value=parse_json(string='{"port": 8080}')) %}
2139+
Port: {{ config.port }}
2140+
2141+
{# Debug in a pipeline #}
2142+
Result: {{ get_env(name="PATH") | debug }}
2143+
2144+
{# Debug intermediate values #}
2145+
{% set users = debug(value=filter_env(pattern="USER_*")) %}
2146+
Found {{ users | length }} user variables
2147+
```
2148+
2149+
**Output to stderr:**
2150+
```
2151+
[DEBUG] {"port": 8080}
2152+
[DEBUG] /usr/local/bin:/usr/bin:/bin
2153+
[DEBUG] [{"key": "USER_NAME", "value": "admin"}]
2154+
```
2155+
2156+
#### `type_of(value)`
2157+
2158+
Get the type of a value. Returns a string describing the value type.
2159+
2160+
**Arguments:**
2161+
- `value` (required) - Value to check
2162+
2163+
**Returns:** String type name: `"string"`, `"number"`, `"bool"`, `"array"`, `"object"`, `"undefined"`
2164+
2165+
**Examples:**
2166+
```jinja
2167+
{{ type_of(value="hello") }} {# Output: string #}
2168+
{{ type_of(value=123) }} {# Output: number #}
2169+
{{ type_of(value=true) }} {# Output: bool #}
2170+
{{ type_of(value=[1,2,3]) }} {# Output: array #}
2171+
2172+
{# Conditional logic based on type #}
2173+
{% set data = get_env(name="DATA", default="[]") %}
2174+
{% if type_of(value=data) == "string" %}
2175+
{% set data = parse_json(string=data) %}
2176+
{% endif %}
2177+
2178+
{# Type-safe processing #}
2179+
{% if type_of(value=config.workers) == "number" %}
2180+
Workers: {{ config.workers }}
2181+
{% else %}
2182+
Workers: {{ config.workers | int }}
2183+
{% endif %}
2184+
```
2185+
2186+
#### `inspect(value)`
2187+
2188+
Pretty-print a value's structure to stderr and return it unchanged. Shows detailed structure of complex objects and arrays.
2189+
2190+
**Arguments:**
2191+
- `value` (required) - Value to inspect
2192+
2193+
**Returns:** The same value (allows chaining)
2194+
2195+
**Examples:**
2196+
```jinja
2197+
{# Inspect complex data structures #}
2198+
{% set config = inspect(value=read_json_file(path="config.json")) %}
2199+
2200+
{# Inspect and continue #}
2201+
{% set env_vars = inspect(value=filter_env(pattern="DB_*")) %}
2202+
Database variables: {{ env_vars | length }}
2203+
```
2204+
2205+
**Output to stderr:**
2206+
```
2207+
[INSPECT] {
2208+
"database": {
2209+
"host": "localhost",
2210+
"port": 5432,
2211+
"name": "myapp"
2212+
},
2213+
"redis": {
2214+
"host": "localhost",
2215+
"port": 6379
2216+
}
2217+
}
2218+
```
2219+
2220+
#### `assert(condition, message)`
2221+
2222+
Assert that a condition is true, otherwise abort rendering with an error message.
2223+
2224+
**Arguments:**
2225+
- `condition` (required) - Boolean condition to check
2226+
- `message` (optional) - Error message if assertion fails (default: "Assertion failed")
2227+
2228+
**Returns:** `true` if condition passes
2229+
2230+
**Examples:**
2231+
```jinja
2232+
{# Assert required environment variable #}
2233+
{% set port = get_env(name="PORT", default="") %}
2234+
{{ assert(condition=port != "", message="PORT environment variable is required") }}
2235+
2236+
{# Assert file exists before reading #}
2237+
{{ assert(condition=file_exists(path="config.json"), message="config.json not found") }}
2238+
{% set config = read_file(path="config.json") %}
2239+
2240+
{# Assert valid range #}
2241+
{% set workers = get_env(name="WORKERS", default="4") | int %}
2242+
{{ assert(condition=workers >= 1 and workers <= 100, message="WORKERS must be between 1 and 100") }}
2243+
2244+
{# Assert valid email format #}
2245+
{% set admin_email = get_env(name="ADMIN_EMAIL") %}
2246+
{{ assert(condition=is_email(string=admin_email), message="ADMIN_EMAIL must be valid email") }}
2247+
```
2248+
2249+
**Error output (if assertion fails):**
2250+
```
2251+
Error: PORT environment variable is required
2252+
```
2253+
2254+
#### `warn(message)`
2255+
2256+
Print a warning message to stderr and continue rendering. Non-fatal warnings for deprecated features or missing optional configuration.
2257+
2258+
**Arguments:**
2259+
- `message` (required) - Warning message
2260+
2261+
**Returns:** Empty string (no template output)
2262+
2263+
**Examples:**
2264+
```jinja
2265+
{# Warn about missing optional config #}
2266+
{% if not file_exists(path="custom.conf") %}
2267+
{{ warn(message="custom.conf not found, using defaults") }}
2268+
{% endif %}
2269+
2270+
{# Warn about deprecated environment variable #}
2271+
{% set old_var = get_env(name="DEPRECATED_VAR", default="") %}
2272+
{% if old_var %}
2273+
{{ warn(message="DEPRECATED_VAR is deprecated, use NEW_VAR instead") }}
2274+
{% set new_var = old_var %}
2275+
{% else %}
2276+
{% set new_var = get_env(name="NEW_VAR", default="default") %}
2277+
{% endif %}
2278+
2279+
{# Warn about potentially unsafe configuration #}
2280+
{% set debug = get_env(name="DEBUG", default="false") %}
2281+
{% set env = get_env(name="APP_ENV", default="development") %}
2282+
{% if debug == "true" and env == "production" %}
2283+
{{ warn(message="WARNING: DEBUG mode enabled in production environment") }}
2284+
{% endif %}
2285+
```
2286+
2287+
**Output to stderr:**
2288+
```
2289+
[WARNING] custom.conf not found, using defaults
2290+
[WARNING] DEPRECATED_VAR is deprecated, use NEW_VAR instead
2291+
[WARNING] WARNING: DEBUG mode enabled in production environment
2292+
```
2293+
2294+
#### `abort(message)`
2295+
2296+
Immediately abort template rendering with an error message. Use for critical failures where rendering should not continue.
2297+
2298+
**Arguments:**
2299+
- `message` (required) - Error message
2300+
2301+
**Returns:** Never returns (always throws error)
2302+
2303+
**Examples:**
2304+
```jinja
2305+
{# Abort if critical file missing #}
2306+
{% if not file_exists(path="critical.conf") %}
2307+
{{ abort(message="Critical configuration file 'critical.conf' is missing") }}
2308+
{% endif %}
2309+
2310+
{# Abort if environment is invalid #}
2311+
{% set env = get_env(name="APP_ENV", default="") %}
2312+
{% if env not in ["development", "staging", "production"] %}
2313+
{{ abort(message="Invalid APP_ENV: must be development, staging, or production, got: " ~ env) }}
2314+
{% endif %}
2315+
2316+
{# Abort on validation failure #}
2317+
{% set port = get_env(name="PORT", default="8080") | int %}
2318+
{% if port < 1024 or port > 65535 %}
2319+
{{ abort(message="Invalid PORT: must be between 1024 and 65535, got: " ~ port) }}
2320+
{% endif %}
2321+
2322+
{# Abort if required secrets are missing #}
2323+
{% set api_key = get_env(name="API_KEY", default="") %}
2324+
{% set db_password = get_env(name="DB_PASSWORD", default="") %}
2325+
{% if api_key == "" or db_password == "" %}
2326+
{{ abort(message="Missing required secrets: API_KEY and DB_PASSWORD must be set") }}
2327+
{% endif %}
2328+
```
2329+
2330+
**Error output:**
2331+
```
2332+
Error: Critical configuration file 'critical.conf' is missing
2333+
```
2334+
2335+
**Practical Example - Configuration Validation:**
2336+
```yaml
2337+
# Production Configuration Template
2338+
2339+
# Validate critical environment
2340+
{% set env = get_env(name="APP_ENV", default="") %}
2341+
{{ assert(condition=env in ["staging", "production"], message="APP_ENV must be staging or production") }}
2342+
2343+
# Validate required secrets
2344+
{% set db_url = get_env(name="DATABASE_URL", default="") %}
2345+
{{ assert(condition=db_url != "", message="DATABASE_URL is required") }}
2346+
2347+
{% set api_key = get_env(name="API_KEY", default="") %}
2348+
{{ assert(condition=api_key != "", message="API_KEY is required") }}
2349+
2350+
# Warn about debug mode
2351+
{% set debug = get_env(name="DEBUG", default="false") %}
2352+
{% if debug == "true" %}
2353+
{{ warn(message="DEBUG mode is enabled in " ~ env) }}
2354+
{% endif %}
2355+
2356+
# Debug configuration for troubleshooting
2357+
{% set config = {
2358+
"environment": env,
2359+
"database": db_url,
2360+
"debug": debug
2361+
} %}
2362+
{{ inspect(value=config) }}
2363+
2364+
# Type-safe port configuration
2365+
{% set port = get_env(name="PORT", default="8080") %}
2366+
{% if type_of(value=port) == "string" %}
2367+
{% set port = port | int %}
2368+
{% endif %}
2369+
{{ assert(condition=port > 0 and port < 65536, message="PORT must be valid") }}
2370+
2371+
application:
2372+
environment: {{ env }}
2373+
port: {{ port }}
2374+
debug: {{ debug }}
2375+
database_url: {{ db_url }}
2376+
api_key: {{ api_key }}
2377+
```
2378+
2379+
**Use Cases:**
2380+
- ✅ **Development**: Debug complex data structures with `debug()` and `inspect()`
2381+
- ✅ **Validation**: Ensure configuration correctness with `assert()`
2382+
- ✅ **Type Safety**: Check value types with `type_of()` before operations
2383+
- ✅ **Graceful Degradation**: Use `warn()` for non-critical issues
2384+
- ✅ **Fail Fast**: Use `abort()` for critical failures requiring immediate attention
2385+
21202386
## Advanced Examples
21212387
21222388
### Docker Compose Generator

0 commit comments

Comments
 (0)