Skip to main content

Target Types

Axogen supports a ridiculous number of file formats. Like, probably more than you'll ever need. But hey, when that one project comes along that needs HJSON for some reason, you'll be ready.

The Factory Functions​

Since v0.5.0, each target type has its own factory function. This gives you proper TypeScript IntelliSense and catches mistakes early:

import {defineConfig, json, yaml, env, toml} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: json({
/* ... */
}),
k8s: yaml({
/* ... */
}),
app: env({
/* ... */
}),
cargo: toml({
/* ... */
}),
},
});

All factory functions work the same way - give them a config object, get back a target definition.

JSON Family​

JSON - json()​

Standard JSON. You know what this is.

import {defineConfig, json} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: json({
path: "config.json",
variables: {
name: "MyApp",
version: "1.0.0",
settings: {
debug: false,
port: 3000,
},
},
options: {
space: 2,
},
}),
},
});

JSON5 - json5()​

JSON5 supports comments, trailing commas, and other nice things that regular JSON doesn't:

import {defineConfig, json5} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: json5({
path: "config.json5",
variables: {
name: "MyApp",
features: ["authentication", "logging"],
},
options: {
space: 2,
},
}),
},
});

JSONC - jsonc()​

JSON with Comments (VS Code style):

import {defineConfig, jsonc} from "@axonotes/axogen";

export default defineConfig({
targets: {
vscode: jsonc({
path: ".vscode/settings.json",
variables: {
"typescript.preferences.quoteStyle": "double",
"editor.formatOnSave": true,
},
}),
},
});

HJSON - hjson()​

Human-friendly JSON where quotes are optional and comments work everywhere:

import {defineConfig, hjson} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: hjson({
path: "config.hjson",
variables: {
name: "MyApp",
settings: {
debug: true,
port: 3000,
},
},
}),
},
});

Configuration Formats​

YAML - yaml()​

Because Kubernetes made us all learn YAML:

import {defineConfig, yaml} from "@axonotes/axogen";

export default defineConfig({
targets: {
deployment: yaml({
path: "k8s/deployment.yaml",
variables: {
apiVersion: "apps/v1",
kind: "Deployment",
metadata: {
name: "my-app",
},
spec: {
replicas: 3,
selector: {
matchLabels: {
app: "my-app",
},
},
},
},
options: {
indent: 2,
quotingType: '"',
},
}),
},
});

TOML - toml()​

For your Rust projects and other civilized languages:

import {defineConfig, toml} from "@axonotes/axogen";

export default defineConfig({
targets: {
cargo: toml({
path: "Cargo.toml",
variables: {
package: {
name: "my-rust-app",
version: "0.1.0",
edition: "2021",
},
dependencies: {
serde: "1.0",
tokio: {version: "1.0", features: ["full"]},
},
},
}),
},
});

INI - ini()​

For when it's 1995 again:

import {defineConfig, ini} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: ini({
path: "app.ini",
variables: {
database: {
host: "localhost",
port: 5432,
name: "mydb",
},
logging: {
level: "info",
file: "app.log",
},
},
}),
},
});

Properties - properties()​

Java-style properties files:

import {defineConfig, properties} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: properties({
path: "application.properties",
variables: {
"server.port": 8080,
"spring.datasource.url": "jdbc:postgresql://localhost/db",
"logging.level.com.myapp": "DEBUG",
},
options: {
align: true,
sort: true,
},
}),
},
});

Environment Files​

ENV - env()​

The classic .env file:

import {defineConfig, env} from "@axonotes/axogen";

export default defineConfig({
targets: {
app: env({
path: ".env.production",
variables: {
NODE_ENV: "production",
PORT: 8080,
DATABASE_URL: "postgres://prod-server/db",
API_KEY: "your-api-key-here",
},
}),
},
});

Data Formats​

XML - xml()​

import {defineConfig, xml} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: xml({
path: "config.xml",
variables: {
configuration: {
database: {
host: "localhost",
port: 5432,
},
features: {
feature: [
{name: "auth", enabled: true},
{name: "logging", enabled: false},
],
},
},
},
options: {
format: true,
indentBy: " ",
},
}),
},
});

CSV - csv()​

Spreadsheet-friendly data:

import {defineConfig, csv} from "@axonotes/axogen";

export default defineConfig({
targets: {
users: csv({
path: "users.csv",
variables: [
{name: "John", email: "john@example.com", role: "admin"},
{name: "Jane", email: "jane@example.com", role: "user"},
],
options: {
header: true,
delimiter: ",",
},
}),
},
});

CSON - cson()​

CoffeeScript Object Notation (remember CoffeeScript?):

import {defineConfig, cson} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: cson({
path: "config.cson",
variables: {
name: "MyApp",
settings: {
debug: true,
port: 3000,
},
},
}),
},
});

Template Files​

Template - template()​

For when you need full control. Supports Nunjucks, Handlebars, and Mustache:

import {defineConfig, template} from "@axonotes/axogen";

export default defineConfig({
targets: {
nginx: template({
path: "nginx.conf",
template: "nginx.conf.njk",
engine: "nunjucks",
variables: {
serverName: "example.com",
port: 80,
upstreams: [
{name: "app1", host: "localhost:3000"},
{name: "app2", host: "localhost:3001"},
],
},
}),
},
});

Your nginx.conf.njk template file would contain template syntax like {{ serverName }} and {% for upstream in upstreams %}.

Schema Validation​

Every target type supports optional Zod schema validation:

import {defineConfig, json} from "@axonotes/axogen";
import * as z from "zod";

export default defineConfig({
targets: {
config: json({
path: "config.json",
schema: z.object({
name: z.string().min(1),
port: z.number().min(1).max(65535),
features: z.array(z.string()),
}),
variables: {
name: "MyApp",
port: 3000,
features: ["auth", "logging"],
},
}),
},
});

If your variables don't match the schema, you'll get helpful error messages at build time.

Common Options​

All targets support these common options:

  • condition - Only generate if this boolean is true
  • backup - Backup the existing file before overwriting
  • generate_meta - Add metadata to the target at runtime (time, settings, generator, etc.). Default is false
import {defineConfig, json} from "@axonotes/axogen";

export default defineConfig({
targets: {
config: json({
path: "config.json",
variables: {name: "MyApp"},
condition: process.env.NODE_ENV === "production",
backup: true,
generate_meta: true,
}),
},
});

What's Next?​

Now you know about all the formats. Time to learn about:

Pick your format, generate your files, profit.