@axonotes/axogen
Version:
TypeScript-native configuration system that unifies typed environment variables, code generation, and task management for any project
1,536 lines (1,510 loc) • 126 kB
JavaScript
#!/usr/bin/env node
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
// package.json
var require_package = __commonJS((exports, module) => {
module.exports = {
name: "@axonotes/axogen",
version: "0.5.7",
description: "TypeScript-native configuration system that unifies typed environment variables, code generation, and task management for any project",
type: "module",
main: "dist/index.cjs",
module: "dist/index.js",
types: "dist/index.d.ts",
exports: {
".": {
import: {
types: "./dist/index.d.ts",
default: "./dist/index.js"
},
require: {
types: "./dist/index.d.ts",
default: "./dist/index.cjs"
}
}
},
bin: {
axogen: "./bin/axogen.js"
},
files: [
"bin/axogen.js",
"bin/axogen.cmd",
"dist"
],
scripts: {
build: "bun run build.ts",
preview: "bun run format && bun test && bun run build && bun link",
pub: "bun run format && bun test && bun run build && bun publish",
"test:local": "bun run build && ./bin/axogen.js --version",
"docs:start": "cd website && bun run start",
"docs:build": "cd website && bun run build",
"docs:serve": "cd website && bun run serve",
format: "prettier --write .",
check: "tsc --noEmit",
prepare: "husky"
},
homepage: "https://axonotes.github.io/axogen/",
repository: {
type: "git",
url: "https://github.com/axonotes/axogen.git"
},
bugs: {
url: "https://github.com/axonotes/axogen/issues"
},
funding: {
type: "github",
url: "https://github.com/sponsors/imgajeed76"
},
keywords: [
"typescript",
"configuration",
"environment-variables",
"config-management",
"task-management",
"cli",
"dotenv",
"yaml",
"json",
"toml",
"template",
"monorepo",
"docker",
"kubernetes",
"type-safety",
"zod",
"code-generation",
"env-files",
"typescript-config",
"config-sync",
"developer-tools",
"devtools",
"build-tools",
"typescript-validation",
"environment-config",
"config-system",
"typescript-native",
"type-safe-config",
"env-management",
"config-cli",
"developer-productivity",
"typescript-tools"
],
author: {
name: "Oliver Seifert",
url: "https://github.com/imgajeed76"
},
license: "MIT",
dependencies: {
"@dotenvx/dotenvx": "^1.48.3",
"@iarna/toml": "^2.2.5",
"@types/cson": "^7.20.3",
"@types/hjson": "^2.4.6",
"@types/ini": "^4.1.1",
"@types/js-yaml": "^4.0.9",
"@types/papaparse": "^5.3.16",
ansis: "^4.1.0",
chalk: "^5.4.1",
commander: "^14.0.0",
cson: "^8.4.0",
"fast-xml-parser": "^5.2.5",
handlebars: "^4.7.8",
hjson: "^3.2.2",
ini: "^5.0.0",
jiti: "^2.4.2",
"js-yaml": "^4.1.0",
json5: "^2.2.3",
"jsonc-parser": "^3.3.1",
mustache: "^4.2.0",
nunjucks: "^3.2.4",
papaparse: "^5.5.3",
"properties-file": "^3.5.13",
tsx: "^4.20.3",
zod: "^4.0.5"
},
devDependencies: {
"@types/bun": "latest",
"@types/mustache": "^4.2.6",
"@types/nunjucks": "^3.2.6",
husky: "^9.1.7",
"lint-staged": "^16.1.2",
prettier: "3.6.2",
tsup: "^8.5.0",
typescript: "^5.8.3"
},
peerDependencies: {
typescript: "^5"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
},
engines: {
node: ">=18",
bun: ">=1.2"
}
};
});
// src/cli-helpers/index.ts
import { Command as Command4 } from "commander";
// src/utils/helpers.ts
function zodIssuesToErrors(issues) {
return issues.map((issue) => {
const field = formatFieldPath(issue.path);
let type = "invalid";
let message = issue.message;
switch (issue.code) {
case "invalid_type": {
const typedIssue = issue;
const isMissing = issue.message.includes("received undefined") || issue.message.includes("Required") || issue.message.includes("required");
type = isMissing ? "missing" : "type";
if (type === "missing") {
message = field ? `${field} is required` : "This field is required";
} else {
if (typedIssue.expected) {
message = field ? `${field} must be a ${typedIssue.expected}` : `Must be a ${typedIssue.expected}`;
} else {
const match = issue.message.match(/expected (\w+)/);
const expectedType = match ? match[1] : "valid value";
message = field ? `${field} must be a ${expectedType}` : `Must be a ${expectedType}`;
}
}
break;
}
case "too_small": {
const sizeIssue = issue;
if (sizeIssue.minimum !== undefined) {
if (field.includes(".") || field.includes("[")) {
if (sizeIssue.inclusive) {
message = field ? `${field} must be at least ${sizeIssue.minimum}` : `Must be at least ${sizeIssue.minimum}`;
} else {
message = field ? `${field} must be greater than ${sizeIssue.minimum}` : `Must be greater than ${sizeIssue.minimum}`;
}
} else {
const minValue = sizeIssue.minimum;
if (typeof minValue === "number" && minValue < 1000 && minValue > -1000) {
const unit = minValue === 1 ? "character" : "characters";
message = field ? `${field} must be at least ${minValue} ${unit}` : `Must be at least ${minValue} ${unit}`;
} else {
const comparator = sizeIssue.inclusive ? ">=" : ">";
message = field ? `${field} must be ${comparator} ${minValue}` : `Must be ${comparator} ${minValue}`;
}
}
}
break;
}
case "too_big": {
const sizeIssue = issue;
if (sizeIssue.maximum !== undefined) {
if (field.includes(".") || field.includes("[")) {
if (sizeIssue.inclusive) {
message = field ? `${field} must be at most ${sizeIssue.maximum}` : `Must be at most ${sizeIssue.maximum}`;
} else {
message = field ? `${field} must be less than ${sizeIssue.maximum}` : `Must be less than ${sizeIssue.maximum}`;
}
} else {
const maxValue = sizeIssue.maximum;
if (typeof maxValue === "number" && maxValue < 1000 && maxValue > 0) {
const unit = maxValue === 1 ? "character" : "characters";
message = field ? `${field} must be at most ${maxValue} ${unit}` : `Must be at most ${maxValue} ${unit}`;
} else {
const comparator = sizeIssue.inclusive ? "<=" : "<";
message = field ? `${field} must be ${comparator} ${maxValue}` : `Must be ${comparator} ${maxValue}`;
}
}
}
break;
}
case "invalid_format": {
const formatIssue = issue;
if (formatIssue.format) {
const formatMessages = {
email: "valid email address",
url: "valid URL",
uuid: "valid UUID",
regex: "valid format",
cuid: "valid CUID",
cuid2: "valid CUID2",
ulid: "valid ULID",
datetime: "valid datetime",
ip: "valid IP address",
base64: "valid base64 string",
nanoid: "valid NanoID"
};
const formatName = formatMessages[formatIssue.format] || "valid format";
message = field ? `${field} must be a ${formatName}` : `Must be a ${formatName}`;
}
break;
}
case "invalid_value": {
const valueIssue = issue;
if (valueIssue.options && Array.isArray(valueIssue.options)) {
message = field ? `${field} must be one of: ${valueIssue.options.join(", ")}` : `Must be one of: ${valueIssue.options.join(", ")}`;
} else if (valueIssue.expected) {
message = field ? `${field} must be ${valueIssue.expected}` : `Must be ${valueIssue.expected}`;
}
break;
}
case "unrecognized_keys": {
const keysIssue = issue;
if (keysIssue.keys && Array.isArray(keysIssue.keys)) {
const keys = keysIssue.keys.join(", ");
message = field ? `${field} contains unrecognized keys: ${keys}` : `Unrecognized keys: ${keys}`;
}
break;
}
case "invalid_union": {
message = field ? `${field} does not match any of the expected types` : "Does not match any of the expected types";
break;
}
case "invalid_key": {
message = field ? `${field} contains an invalid key` : "Contains an invalid key";
break;
}
case "invalid_element": {
message = field ? `${field} contains an invalid element` : "Contains an invalid element";
break;
}
case "not_multiple_of": {
const multipleIssue = issue;
if (multipleIssue.multipleOf !== undefined) {
message = field ? `${field} must be a multiple of ${multipleIssue.multipleOf}` : `Must be a multiple of ${multipleIssue.multipleOf}`;
}
break;
}
case "custom": {
if (!message || message === "Invalid input") {
message = field ? `${field} is invalid` : "Invalid value";
}
break;
}
default: {
if (!message || message === "Invalid input") {
message = field ? `${field} is invalid` : "Invalid value";
}
break;
}
}
return {
field,
message,
type
};
});
}
function formatFieldPath(path) {
if (path.length === 0)
return "";
return path.reduce((acc, segment, index) => {
if (typeof segment === "number") {
return `${acc}[${segment}]`;
}
if (index === 0) {
return String(segment);
}
return `${acc}.${String(segment)}`;
}, "");
}
// src/cli-helpers/runner.ts
import * as z2 from "zod";
// src/cli-helpers/zod_helpers.ts
import * as z from "zod";
function getCommandHelp(command) {
if (typeof command === "string" || typeof command === "function") {
return;
}
return command.help;
}
function isStringCommand(command) {
return typeof command === "object" && command.type === "string";
}
function isAdvancedCommand(command) {
return typeof command === "object" && command.type === "advanced";
}
function isGroupCommand(command) {
return typeof command === "object" && command.type === "group";
}
function validateOptionsWithZod(rawOptions, optionsSchema) {
const processedOptions = { ...rawOptions };
for (const [key, schema] of Object.entries(optionsSchema)) {
const info = analyzeZodSchema(schema);
if (info.baseType === "array" && typeof processedOptions[key] === "string") {
processedOptions[key] = processedOptions[key].split(",").map((s) => s.trim());
}
}
return z.object(optionsSchema).parse(processedOptions);
}
function validateArgsWithZod(rawArgs, argsSchema) {
const argNames = Object.keys(argsSchema);
const argsObject = {};
for (let i = 0;i < argNames.length; i++) {
const argName = argNames[i];
const value = rawArgs[i];
if (value !== undefined) {
argsObject[argName] = value;
}
}
try {
return z.object(argsSchema).parse(argsObject);
} catch (error) {
if (error instanceof z.ZodError) {
throw new z.ZodError([
...error.issues.map((issue) => ({
...issue,
path: ["args", ...issue.path]
}))
]);
}
throw error;
}
}
function analyzeZodSchema(schema) {
let currentSchema = schema;
let isOptional = false;
let description = undefined;
while (currentSchema) {
if (!description) {
description = extractDescription(currentSchema);
}
const type = getZodType(currentSchema);
if (type === "optional" || type === "nullable" || type === "default") {
isOptional = true;
if (canUnwrap(currentSchema)) {
currentSchema = currentSchema.unwrap();
} else {
break;
}
} else {
break;
}
}
const baseType = getZodType(currentSchema);
return {
baseType,
isOptional,
description
};
}
function getZodType(schema) {
return schema._zod?.def?.type || "unknown";
}
function extractDescription(schema) {
try {
const meta = schema.meta();
if (meta && typeof meta.description === "string") {
return meta.description;
}
} catch {}
return;
}
function canUnwrap(schema) {
return typeof schema.unwrap === "function";
}
// src/utils/console/themes.ts
import chalk2 from "chalk";
// src/utils/console/formatter.ts
import chalk from "chalk";
class XMLParser {
input;
position;
constructor(input) {
this.input = input;
this.position = 0;
}
parse() {
const root = [];
const stack = [{ children: root }];
while (this.position < this.input.length) {
if (this.peek() === "\\" && this.peekNext() === "<") {
const text = this.parseText();
if (text.length > 0) {
const parent = stack[stack.length - 1];
if (!parent) {
throw new Error("No parent node found for text content");
}
parent.children.push({
text,
children: []
});
}
} else if (this.peek() === "<") {
const tag = this.parseTag();
if (tag) {
if (tag.isClosing) {
if (stack.length > 1) {
stack.pop();
}
} else {
const node = {
tag: tag.name,
children: []
};
const parent = stack[stack.length - 1];
if (!parent) {
throw new Error("No parent node found for new tag");
}
parent.children.push(node);
if (!tag.isSelfClosing) {
stack.push(node);
}
}
}
} else {
const text = this.parseText();
if (text.length > 0) {
const parent = stack[stack.length - 1];
if (!parent) {
throw new Error("No parent node found for text content");
}
parent.children.push({
text,
children: []
});
}
}
}
return root;
}
peek() {
return this.input[this.position] || "";
}
peekNext() {
return this.input[this.position + 1] || "";
}
advance() {
const char = this.input[this.position] || "";
this.position++;
return char;
}
parseTag() {
if (this.peek() !== "<")
return null;
this.advance();
let isClosing = false;
if (this.peek() === "/") {
isClosing = true;
this.advance();
}
let tagName = "";
while (this.position < this.input.length && this.peek() !== ">" && this.peek() !== "/" && !this.isWhitespace(this.peek())) {
tagName += this.advance();
}
while (this.position < this.input.length && this.peek() !== ">" && this.peek() !== "/") {
this.advance();
}
let isSelfClosing = false;
if (this.peek() === "/") {
isSelfClosing = true;
this.advance();
}
if (this.peek() === ">") {
this.advance();
}
return {
name: tagName.trim(),
isClosing,
isSelfClosing
};
}
parseText() {
let text = "";
while (this.position < this.input.length) {
const current = this.peek();
if (current === "\\") {
const next = this.peekNext();
if (next === "<" || next === ">") {
text += next;
this.advance();
this.advance();
} else if (next === "\\") {
text += "\\";
this.advance();
this.advance();
} else {
text += this.advance();
}
} else if (current === "<") {
break;
} else {
text += this.advance();
}
}
return text;
}
isWhitespace(char) {
return /\s/.test(char);
}
}
class TreeTransformer {
transformers;
constructor(transformers) {
this.transformers = transformers;
}
transform(nodes) {
return nodes.map((node) => this.transformNode(node)).join("");
}
transformNode(node) {
const childrenContent = node.children.map((child) => this.transformNode(child)).join("");
if (node.text !== undefined) {
return node.text;
}
if (node.tag && this.transformers[node.tag]) {
return this.transformers[node.tag](childrenContent);
}
console.warn(chalk.redBright(`No transformer found for tag: ${node.tag}. Returning content as-is.`));
return childrenContent;
}
}
function parseAndTransform(input, transformers) {
const parser = new XMLParser(input);
const tree = parser.parse();
const transformer = new TreeTransformer(transformers);
return transformer.transform(tree);
}
// src/env/helpers.ts
import { exec } from "child_process";
import * as os from "os";
import * as path from "path";
import * as fs from "fs/promises";
function promisifyExec(command) {
return new Promise((resolve, reject) => {
exec(command, (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}
async function setPersistentEnvVariable(key, value) {
const platform2 = os.platform();
switch (platform2) {
case "win32":
await setWindowsPersistent(key, value);
break;
case "darwin":
case "linux":
await setUnixPersistent(key, value);
break;
default:
throw new Error(`Cant set environment variable. Unsupported platform: ${platform2}`);
}
process.env[key] = value;
}
async function setWindowsPersistent(key, value) {
try {
await promisifyExec(`setx ${key} "${value}"`);
} catch (error) {
console.error(`Failed to set ${key} persistently for Windows user:`, error);
throw new Error(`Failed to set environment variable ${key} on Windows`);
}
}
async function setUnixPersistent(key, value) {
const homeDir = os.homedir();
const shell = process.env.SHELL || "/bin/bash";
let profileFiles;
if (shell.includes("zsh")) {
profileFiles = [".zshrc", ".zprofile"];
} else if (shell.includes("bash")) {
profileFiles = [".bashrc", ".bash_profile", ".profile"];
} else if (shell.includes("fish")) {
profileFiles = [".config/fish/config.fish"];
} else {
profileFiles = [".profile"];
}
const exportLine = `export ${key}="${value}"`;
for (const profileFile of profileFiles) {
const filePath = path.join(homeDir, profileFile);
try {
await fs.access(filePath);
const content = await fs.readFile(filePath, "utf-8");
const regex = new RegExp(`^export ${key}=.*$`, "m");
if (regex.test(content)) {
const newContent = content.replace(regex, exportLine);
await fs.writeFile(filePath, newContent);
} else {
await fs.appendFile(filePath, `
${exportLine}
`);
}
console.log(`---> Run 'source ~/${profileFile}' to apply changes or restart your terminal.`);
break;
} catch (error) {}
}
}
// src/utils/console/themes.ts
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (!result)
throw new Error(`Invalid hex color: ${hex}`);
return [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
];
}
function rgbToHex(r, g, b) {
return "#" + [r, g, b].map((x) => {
const hex = Math.round(x).toString(16);
return hex.length === 1 ? "0" + hex : hex;
}).join("");
}
function interpolateColor(color1, color2, factor) {
const [r1, g1, b1] = hexToRgb(color1);
const [r2, g2, b2] = hexToRgb(color2);
const r = r1 + factor * (r2 - r1);
const g = g1 + factor * (g2 - g1);
const b = b1 + factor * (b2 - b1);
return rgbToHex(r, g, b);
}
function generateNeutralScale(lightColor, darkColor) {
const scalePoints = [0, 100, 200, 300, 400, 500, 600, 700, 800, 900];
const neutrals = {};
scalePoints.forEach((point) => {
const factor = point / 900;
neutrals[point.toString()] = interpolateColor(lightColor, darkColor, factor);
});
return neutrals;
}
var vscode = {
name: "vscode",
description: "VS Code's default dark theme with balanced contrast",
colors: {
primary: "#007fd4",
secondary: "#ff6b35",
success: "#0dbc79",
warning: "#ffcc02",
danger: "#f14c4c",
neutralLight: "#ffffff",
neutralDark: "#1e1e1e"
}
};
var astrodark = {
name: "astrodark",
description: "Sophisticated dark theme with balanced vibrant colors",
colors: {
primary: "#CC83E3",
secondary: "#50A4E9",
success: "#75AD47",
warning: "#D09214",
danger: "#F8747E",
neutralLight: "#ffffff",
neutralDark: "#111317"
}
};
var aura = {
name: "aura",
description: "Vibrant neon-inspired dark theme with electric colors",
colors: {
primary: "#A277FF",
secondary: "#4D8AFF",
success: "#61FFCA",
warning: "#FFCA85",
danger: "#FF6767",
neutralLight: "#ffffff",
neutralDark: "#110F18"
}
};
var doomOne = {
name: "doom-one",
description: "Classic sophisticated dark theme with muted vibrancy",
colors: {
primary: "#c678dd",
secondary: "#51afef",
success: "#98be65",
warning: "#ecbe7b",
danger: "#ff6c6b",
neutralLight: "#ffffff",
neutralDark: "#1b2229"
}
};
var catppuccinMocha = {
name: "catppuccin-mocha",
description: "Soothing pastel theme for comfortable long sessions",
colors: {
primary: "#cba6f7",
secondary: "#89b4fa",
success: "#a6e3a1",
warning: "#f9e2af",
danger: "#f38ba8",
neutralLight: "#ffffff",
neutralDark: "#1e1e2e"
}
};
var themes = {
vscode,
astrodark,
aura,
"doom-one": doomOne,
"catppuccin-mocha": catppuccinMocha
};
var themeColorNames = [
"primary",
"secondary",
"success",
"warning",
"danger",
"neutral_0",
"neutral_100",
"neutral_200",
"neutral_300",
"neutral_400",
"neutral_500",
"neutral_600",
"neutral_700",
"neutral_800",
"neutral_900"
];
var colorizeColorNames = [
...themeColorNames,
"text",
"textSecondary",
"textMuted",
"background",
"backgroundLight",
"border"
];
var DEFAULT_THEME = process.env.AXOGEN_THEME || "vscode";
var DEFAULT_ENABLE_COLOR = (process.env.AXOGEN_ENABLE_COLOR || "true").toLowerCase() === "true";
function getTheme(name) {
if (!name || !(name in themes)) {
return themes[DEFAULT_THEME];
}
return themes[name];
}
function isValidTheme(name) {
return name in themes;
}
class ThemeManager {
currentTheme;
colorizer;
neutralColors;
transformers;
enableColor = DEFAULT_ENABLE_COLOR;
constructor() {
this.currentTheme = getTheme(DEFAULT_THEME);
this.neutralColors = generateNeutralScale(this.currentTheme.colors.neutralLight, this.currentTheme.colors.neutralDark);
this.colorizer = this.createColorizer(this.currentTheme);
this.transformers = this.createTransformers();
}
createColorizer(theme) {
const colorizer = {};
if (!this.enableColor) {
colorizeColorNames.forEach((name) => {
colorizer[name] = chalk2.white.bgBlack;
});
return colorizer;
}
colorizer.primary = chalk2.hex(theme.colors.primary);
if (theme.colors.secondary) {
colorizer.secondary = chalk2.hex(theme.colors.secondary);
}
colorizer.success = chalk2.hex(theme.colors.success);
colorizer.warning = chalk2.hex(theme.colors.warning);
colorizer.danger = chalk2.hex(theme.colors.danger);
Object.entries(this.neutralColors).forEach(([level, color]) => {
colorizer[`neutral_${level}`] = chalk2.hex(color);
});
colorizer.text = chalk2.hex(this.neutralColors["200"]);
colorizer.textSecondary = chalk2.hex(this.neutralColors["600"]);
colorizer.textMuted = chalk2.hex(this.neutralColors["400"]);
colorizer.background = chalk2.hex(this.neutralColors["900"]);
colorizer.backgroundLight = chalk2.hex(this.neutralColors["100"]);
colorizer.border = chalk2.hex(this.neutralColors["300"]);
return colorizer;
}
createTransformers() {
return {
b: (text) => this.colorizer.text.bold(text),
d: (text) => this.colorizer.text.dim(text),
i: (text) => this.colorizer.text.italic(text),
u: (text) => this.colorizer.text.underline(text),
s: (text) => this.colorizer.text.strikethrough(text),
primary: (text) => this.colorizer.primary(text),
secondary: (text) => this.colorizer.secondary(text),
success: (text) => this.colorizer.success(text),
warning: (text) => this.colorizer.warning(text),
danger: (text) => this.colorizer.danger(text),
error: (text) => this.colorizer.danger(text),
muted: (text) => this.colorizer.textMuted(text),
subtle: (text) => this.colorizer.textSecondary(text),
text: (text) => this.colorizer.text(text),
"dim-text": (text) => this.colorizer.textSecondary(text),
r: (text) => chalk2.reset(text)
};
}
get colorize() {
return this.colorizer;
}
get theme() {
return this.currentTheme;
}
get neutrals() {
return this.neutralColors;
}
setTheme(name, persistent = false) {
if (!isValidTheme(name)) {
throw new Error(`Invalid theme name: ${name}`);
}
this.currentTheme = getTheme(name);
this.updateAll();
process.env.AXOGEN_THEME = this.currentTheme.name;
if (!persistent) {
return;
}
setPersistentEnvVariable("AXOGEN_THEME", this.currentTheme.name).catch(() => {
console.warn("Failed to save theme to persistent environment");
});
}
colorOutput(enable, persistent = false) {
this.enableColor = enable;
this.updateAll();
process.env.AXOGEN_ENABLE_COLOR = String(enable);
if (!persistent) {
return;
}
setPersistentEnvVariable("AXOGEN_ENABLE_COLOR", String(enable)).catch(() => {
console.warn("Failed to save color output setting to persistent environment");
});
}
updateAll() {
this.neutralColors = generateNeutralScale(this.currentTheme.colors.neutralLight, this.currentTheme.colors.neutralDark);
this.colorizer = this.createColorizer(this.currentTheme);
this.transformers = this.createTransformers();
}
getColor(colorName) {
const theme = this.currentTheme;
if (colorName.startsWith("neutral_")) {
const level = colorName.split("_")[1];
return this.neutralColors[level] || theme.colors.neutralLight;
}
return theme.colors[colorName];
}
getNeutralScale() {
return { ...this.neutralColors };
}
format(xml) {
return parseAndTransform(xml, this.transformers);
}
}
var themeManager = new ThemeManager;
// src/utils/console/logger.ts
function format(xml) {
return themeManager.format(xml);
}
function logF(xml) {
console.log(format(xml));
}
var logger = {
logF: (xml) => logF(xml),
format: (xml) => format(xml),
success: (message) => logF(`<success>${message}</success>`),
error: (message) => logF(`<error>${message}</error>`),
warn: (message) => logF(`<warning>${message}</warning>`),
info: (message) => logF(` <primary>${message}</primary>`),
debug: (message) => console.debug(message),
trace: (message) => console.trace(message),
file: (message, path2) => {
logF(` <primary>+</primary> ${message} <subtle>${path2 ? `[${path2}]` : ""}</subtle>`);
},
command: (message) => {
logF(`<secondary>></secondary> ${message}`);
},
start: (message) => {
logF(`<primary>➤</primary> ${message}`);
},
logIssues: (logConfig) => {
console.log();
logF(`<error>${logConfig.title}</error>`);
console.log(` ${logConfig.subtitle}`);
console.log();
const groupedItems = logConfig.items.reduce((groups, item) => {
if (!groups[item.level]) {
groups[item.level] = [];
}
groups[item.level].push(item);
return groups;
}, {});
Object.entries(groupedItems).forEach(([levelName, items]) => {
const levelConfig = logConfig.levels[levelName];
if (!levelConfig)
return;
logF(` <${levelConfig.color}>${levelName.toUpperCase()}</${levelConfig.color}> <subtle>${items.length}</subtle>`);
items.forEach((item) => {
const itemIcon = `<${levelConfig.color}>•</${levelConfig.color}>`;
const key = `<primary>${item.key}</primary>`;
const description = item.description;
const extra = `<subtle>${item.extra ? ` [${item.extra}]` : ""}</subtle>`;
logF(` ${itemIcon} ${key}: ${description}${extra}`);
});
console.log();
});
logF(` <${logConfig.footerIconColor}>${logConfig.footerIcon}</${logConfig.footerIconColor}>${logConfig.footerIcon ? " " : ""}${logConfig.footer}`);
console.log();
},
validation: (title, errors) => {
const missing = errors.filter((e) => e.type === "missing");
const typeErrors = errors.filter((e) => e.type === "type");
const invalid = errors.filter((e) => e.type === "invalid" || !e.type);
const summaryParts = [
missing.length > 0 && `${missing.length} missing`,
typeErrors.length > 0 && `${typeErrors.length} type error${typeErrors.length !== 1 ? "s" : ""}`,
invalid.length > 0 && `${invalid.length} invalid value${invalid.length !== 1 ? "s" : ""}`
].filter(Boolean);
const subtitle = format(`<subtle>Found:</subtle> ${errors.length} validation error${errors.length !== 1 ? "s" : ""} <subtle>${summaryParts.join(" • ")}</subtle>`);
const items = errors.map((error) => ({
level: error.type === "missing" ? "missing" : error.type === "type" ? "type-error" : "invalid",
key: error.field || "field",
description: error.message,
extra: undefined
}));
logger.logIssues({
title: `✗ ${title}`,
subtitle,
levels: {
missing: { color: "error" },
"type-error": { color: "error" },
invalid: { color: "error" }
},
items,
footer: "Fix these issues before continuing",
footerIcon: "!",
footerIconColor: "warning"
});
},
security: (title, result) => {
const summaryParts = [
result.highConfidenceCount > 0 && `${result.highConfidenceCount} high risk`,
result.mediumConfidenceCount > 0 && `${result.mediumConfidenceCount} medium risk`,
result.lowConfidenceCount > 0 && `${result.lowConfidenceCount} low risk`
].filter(Boolean);
const subtitle = format(`<subtle>Found:</subtle> ${result.totalCount} potential secret${result.totalCount !== 1 ? "s" : ""} <subtle>${summaryParts.join(" • ")}</subtle>`);
const items = result.secretsFound.map((issue) => ({
level: issue.confidence,
key: issue.path || issue.key || "unknown",
description: issue.reason,
extra: issue.category
}));
logger.logIssues({
title: `⚠ ${title}`,
subtitle,
levels: {
high: { color: "error" },
medium: { color: "warning" },
low: { color: "muted" }
},
items,
footer: "Generation blocked for security",
footerIcon: "✗",
footerIconColor: "error"
});
},
header: (title) => {
logF(`<secondary>${"═".repeat(Math.max(title.length + 4, 40))}</secondary>`);
logF(`<secondary> ${title.toUpperCase()} </secondary>`);
logF(`<secondary>${"═".repeat(Math.max(title.length + 4, 40))}</secondary>`);
},
divider: (text) => {
const barLength = 40;
if (text) {
const remaining = barLength - 2 - text.length;
const padding = Math.max(0, Math.floor(remaining / 2));
const line = "─".repeat(padding);
const equalizer = remaining % 2 === 0 ? "" : "─";
logF(`<subtle>${line} ${text} ${line}${equalizer}</subtle>`);
} else {
logF(`<subtle>${"─".repeat(barLength)}</subtle>`);
}
},
bullet: (text, level = 1) => {
const indent = " ".repeat(level);
logF(`<subtle>${indent}•</subtle> ${text}`);
},
list: (items, level = 1) => {
const indent = " ".repeat(level);
items.forEach((item) => {
logF(`<subtle>${indent}•</subtle> ${item}`);
});
},
prefix: {
command: (name, message) => {
logF(`<secondary>[${name}]</secondary> ${message}`);
}
}
};
// src/cli-helpers/runner.ts
class CommandRunner {
async executeCommand(command, options) {
try {
if (typeof command === "string") {
return await this.executeStringCommand(command, options);
}
if (typeof command === "function") {
return await this.executeFunctionCommand(command, options);
}
if (isStringCommand(command)) {
return await this.executeStringCommand(command.command, options);
}
if (isAdvancedCommand(command)) {
return await this.executeAdvancedCommand(command, options);
}
if (isGroupCommand(command)) {
return await this.executeCommandGroup(command, options);
}
return { success: false, error: "Unknown command type" };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error)
};
}
}
async executeStringCommand(command, options) {
try {
const prefix = this.extractCommandPrefix(command);
const result = await liveExec(command, {
cwd: options.global.cwd,
env: options.global.process_env,
outputPrefix: prefix
});
return {
success: result.exitCode === 0,
exitCode: result.exitCode,
error: result.exitCode !== 0 ? `Command exited with code ${result.exitCode}` : undefined
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error)
};
}
}
extractCommandPrefix(command) {
const trimmed = command.trim();
const cdAndMatch = trimmed.match(/cd\s+[^&]*&&\s*(.+)/);
if (cdAndMatch) {
return this.extractCommandPrefix(cdAndMatch[1]);
}
const pipeMatch = trimmed.match(/^([^|]+)/);
const baseCommand = pipeMatch ? pipeMatch[1].trim() : trimmed;
const words = baseCommand.split(/\s+/);
const firstWord = words[0];
const commandMappings = {
npm: "NPM",
yarn: "YARN",
pnpm: "PNPM",
bun: "BUN",
cargo: "CARGO",
rustc: "RUST",
node: "NODE",
deno: "DENO",
python: "PYTHON",
python3: "PYTHON",
pip: "PIP",
git: "GIT",
docker: "DOCKER",
kubectl: "K8S",
helm: "HELM",
terraform: "TF",
aws: "AWS",
gcloud: "GCP",
az: "AZURE",
make: "MAKE",
cmake: "CMAKE",
gcc: "GCC",
clang: "CLANG",
go: "GO",
javac: "JAVA",
java: "JAVA",
mvn: "MAVEN",
gradle: "GRADLE",
dotnet: "DOTNET",
nuget: "NUGET",
composer: "PHP",
php: "PHP",
ruby: "RUBY",
gem: "GEM",
bundle: "BUNDLE",
rails: "RAILS",
mix: "ELIXIR",
iex: "ELIXIR",
stack: "HASKELL",
cabal: "HASKELL",
swift: "SWIFT",
xcodebuild: "XCODE",
flutter: "FLUTTER",
dart: "DART"
};
const mapped = commandMappings[firstWord.toLowerCase()];
if (mapped) {
return mapped;
}
if (firstWord.includes("/")) {
const basename = firstWord.split("/").pop() || firstWord;
return basename.toUpperCase();
}
const withoutExt = firstWord.replace(/\.(exe|sh|bat|cmd|ps1)$/i, "");
return withoutExt.toUpperCase().slice(0, 8);
}
async executeFunctionCommand(fn, options) {
try {
const context = {
global: options.global,
config: options.config
};
await fn(context);
return { success: true };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : String(error)
};
}
}
async executeAdvancedCommand(command, options) {
try {
const validatedOptions = command.options ? validateOptionsWithZod(options.options || {}, command.options) : {};
const validatedArgs = command.args ? validateArgsWithZod(options.args || [], command.args) : {};
await command.exec({
global: options.global,
config: options.config,
options: validatedOptions,
args: validatedArgs
});
return { success: true };
} catch (error) {
if (error instanceof z2.ZodError) {
const validationErrors = zodIssuesToErrors(error.issues);
logger.validation(`Command validation failed: ${command.help || "No description"}`, validationErrors);
return { success: false, error: "Validation failed" };
}
return {
success: false,
error: error instanceof Error ? error.message : String(error)
};
}
}
async executeCommandGroup(group, options) {
const [subcommandName, ...remainingArgs] = options.args || [];
if (!subcommandName) {
if (group.help) {
logger.info(group.help);
console.log();
}
logger.info("Available subcommands:");
console.log();
const commandRows = [];
for (const [name, command] of Object.entries(group.commands)) {
const help = getCommandHelp(command);
commandRows.push({
key: name,
value: help || "No description available"
});
}
if (commandRows.length > 0) {
const maxKeyLength = Math.max(...commandRows.map((row) => row.key.length));
commandRows.forEach((row) => {
const paddedKey = row.key.padEnd(maxKeyLength, " ");
logger.bullet(`${paddedKey} - ${row.value}`);
});
} else {
logger.bullet("No subcommands available");
}
return { success: true };
}
const subcommand = group.commands[subcommandName];
if (!subcommand) {
return {
success: false,
error: `Subcommand "${subcommandName}" not found`
};
}
return this.executeCommand(subcommand, {
...options,
args: remainingArgs
});
}
}
var commandRunner = new CommandRunner;
// src/cli-helpers/index.ts
import { spawn } from "node:child_process";
import { resolve as resolve4, isAbsolute } from "node:path";
// src/version.ts
function getVersion() {
if (true) {
return "0.5.7";
}
try {
const packageJson = require_package();
return packageJson.version;
} catch {
return "dev";
}
}
// src/config/loader.ts
import { resolve, join as join2 } from "node:path";
import { access as access2, constants } from "node:fs/promises";
import { z as z7 } from "zod";
import { createJiti } from "jiti";
// src/config/types/targets.ts
var templateTargetEngines = [
"nunjucks",
"handlebars",
"mustache"
];
function json(config) {
return { type: "json", ...config };
}
// src/config/types/index.ts
import * as z6 from "zod";
// src/config/types/zod_config.ts
import * as z5 from "zod";
// src/config/types/zod_targets.ts
import * as z3 from "zod";
var backupTargetOptionsSchema = z3.object({
enabled: z3.boolean().describe("Whether to create a backup of the target file").default(true).optional(),
folder: z3.string().describe("The path to the backup folder. Defaults to '.axogen/backup/{{path}}'").default("").optional(),
maxBackups: z3.number().describe("The maximum number of backups to keep. Defaults to 5").default(5).optional(),
onConflict: z3.enum(["overwrite", "increment", "skip", "fail"]).describe("What to do when a backup file already exists. Defaults to 'increment'. Mostly not used since filenames are ISO timestamped (so pretty unique).").default("increment").optional()
});
var backupTargetSchema = z3.union([
z3.boolean().describe("Whether to create a backup of the target file"),
backupTargetOptionsSchema
]).default(false);
var baseTargetSchema = z3.object({
path: z3.string().describe("The output path for the target"),
schema: z3.custom((val) => {
return val && typeof val === "object" && (("_def" in val) || ("_zod" in val));
}).describe("The Schema to validate the variables against").optional(),
generate_meta: z3.boolean().describe("Whether to generate metadata for the target").default(false),
condition: z3.boolean().describe("Condition to determine if the target should be generated").default(true).optional(),
backup: backupTargetSchema.optional()
});
var jsonTargetSchema = baseTargetSchema.extend({
type: z3.literal("json").describe("The type of the target, in this case JSON"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var json5TargetSchema = baseTargetSchema.extend({
type: z3.literal("json5").describe("The type of the target, in this case JSON5"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var jsoncTargetSchema = baseTargetSchema.extend({
type: z3.literal("jsonc").describe("The type of the target, in this case JSONC"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var hjsonTargetSchema = baseTargetSchema.extend({
type: z3.literal("hjson").describe("The type of the target, in this case HJSON"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var yamlTargetSchema = baseTargetSchema.extend({
type: z3.literal("yaml").describe("The type of the target, in this case YAML"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var tomlTargetSchema = baseTargetSchema.extend({
type: z3.literal("toml").describe("The type of the target, in this case TOML"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target")
});
var iniTargetSchema = baseTargetSchema.extend({
type: z3.literal("ini").describe("The type of the target, in this case INI"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var propertiesTargetSchema = baseTargetSchema.extend({
type: z3.literal("properties").describe("The type of the target, in this case Properties"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var envTargetSchema = baseTargetSchema.extend({
type: z3.literal("env").describe("The type of the target, in this case Environment Variables"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target")
});
var xmlTargetSchema = baseTargetSchema.extend({
type: z3.literal("xml").describe("The type of the target, in this case XML"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var csvTargetSchema = baseTargetSchema.extend({
type: z3.literal("csv").describe("The type of the target, in this case CSV"),
variables: z3.array(z3.record(z3.string(), z3.any())).describe("Variables to be used in the target"),
options: z3.custom().optional()
});
var csonTargetSchema = baseTargetSchema.extend({
type: z3.literal("cson").describe("The type of the target, in this case CSON"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target")
});
var templateTargetSchema = baseTargetSchema.extend({
type: z3.literal("template").describe("The type of the target, in this case Template"),
engine: z3.enum(templateTargetEngines).describe("The template engine to use").default("nunjucks"),
template: z3.string().describe("The template string or file path"),
variables: z3.record(z3.string(), z3.any()).describe("Variables to be used in the target")
});
var anyTargetSchema = z3.discriminatedUnion("type", [
jsonTargetSchema,
json5TargetSchema,
jsoncTargetSchema,
hjsonTargetSchema,
yamlTargetSchema,
tomlTargetSchema,
iniTargetSchema,
propertiesTargetSchema,
envTargetSchema,
xmlTargetSchema,
csvTargetSchema,
csonTargetSchema,
templateTargetSchema
]).check((ctx) => {
if (ctx.value.schema && ctx.value.variables) {
const result = ctx.value.schema.safeParse(ctx.value.variables);
if (!result.success) {
result.error.issues.forEach((issue) => {
ctx.issues.push({
code: "custom",
message: issue.message,
path: ["variables", ...issue.path],
input: ctx.value
});
});
}
}
});
var allTargetsSchema = z3.record(z3.string(), anyTargetSchema).describe("A record of targets where the key is the target name and the value is the target definition");
// src/config/types/zod_commands.ts
import * as z4 from "zod";
var helpSchema = z4.string().describe("A description of the command, used for help output").optional();
var globalCommandContextSchema = z4.object({
cwd: z4.string().describe("The current working directory"),
process_env: z4.record(z4.string(), z4.any()).describe("The process environment variables"),
verbose: z4.boolean().describe("Whether the command is running in verbose mode")
});
var zodTypeSchema = z4.custom((val) => {
return val && typeof val === "object" && (("_zod" in val) || ("_def" in val));
});
var commandContextSchema = z4.object({
options: z4.record(z4.string(), zodTypeSchema).describe("The options for the command, as a record of Zod types").default({}),
args: z4.record(z4.string(), zodTypeSchema).describe("The arguments for the command, as a record of Zod types").default({}),
global: globalCommandContextSchema.describe("The global context for the command, including cwd and env"),
config: axogenConfigSchema
});
var simpleCommandContextSchema = z4.object({
global: globalCommandContextSchema.describe("The global context for the command, including cwd and env"),
config: axogenConfigSchema
});
var stringCommandSchema = z4.object({
type: z4.literal("string").describe("The type of the command, in this case a string command"),
help: helpSchema,
command: z4.string().describe("The command to be executed, as a string")
});
var groupCommandSchema = z4.object({
type: z4.literal("group").describe("The type of the command, in this case a group command"),
help: helpSchema,
commands: z4.record(z4.string(), z4.lazy(() => anyCommandSchema)).describe("The commands in the group")
});
var advancedCommandSchema = z4.object({
type: z4.literal("advanced").describe("The type of the command, in this case an advanced command"),
help: helpSchema,
options: z4.record(z4.string(), zodTypeSchema).describe("The options for the command, as a record of Zod types").default({}),
args: z4.record(z4.string(), zodTypeSchema).describe("The arguments for the command, as a record of Zod types").default({}),
exec: z4.custom((val) => {
return typeof val === "function";
}).describe("The function to execute for the command")
});
var simpleStringCommandSchema = z4.string().describe("A simple command string, which is executed directly");
var simpleCommandFunctionSchema = z4.custom((val) => {
return typeof val === "function";
}).describe("A simple command function that takes a context object");
var anyCommandSchema = z4.union([
simpleStringCommandSchema,
simpleCommandFunctionSchema,
stringCommandSchema,
groupCommandSchema,
advancedCommandSchema
]);
// src/config/types/zod_config.ts
var axogenConfigSchema = z5.object({
type: z5.literal("AxogenConfig").optional(),
watch: z5.array(z5.string()).optional(),
targets: allTargetsSchema.optional(),
commands: z5.record(z5.string(), anyCommandSchema).optional()
});
// src/config/types/commands.ts
function cmd(config) {
if ("command" in config) {
return {
type: "string",
command: config.command,
help: config.help
};
}
if ("exec" in config) {
return {
type: "advanced",
exec: config.exec,
options: config.options,
args: config.args,
help: config.help
};
}
throw new Error("Invalid configuration object passed to cmd function");
}
// src/config/types/index.ts
function defineConfig(config2) {
try {
return axogenConfigSchema.parse({
...config2,
type: "AxogenConfig"
});
} catch (error) {
if (error instanceof z6.ZodError) {
const validationErrors = zodIssuesToErrors(error.issues);
logger.validation(`Configuration validation failed`, validationErrors);
logger.logF(`<primary>\uD83D\uDCA1</primary> <d>Check your config file structure.</d>`);
throw new Error("Configuration validation failed");
}
throw new Error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
}
}
var conf = defineConfig({
targets: {
someService: json({
path: "output/someService.json",
schema: z6.object({
someVar: z6.string().describe("A variable for the service")
}),
variables: {
someVar: "value"
}
})
},
commands: {
someCommand: cmd({
command: "echo 'Hello, World!'",
help: "A simple command that echoes 'Hello, World!'"
}),
simple: "test",
simpleFunction: (context) => {
context.config.targets.someService.variables.someVar;
},
complex: cmd({
help: "A complex command with options and arguments",
args: {
someArg: z6.number().describe("An argument for the command")
},
exec: (context) => {
const arg = context.args.someArg;
const someVar = context.config.targets.someService.variables.someVar;
}
})
}
});
// src/config/loader.ts
class ConfigLoader {
async load(configPath) {
const resolvedPath = await this.resolveConfigPath(configPath);
try {
let configInput;
if (resolvedPath.endsWith(".ts")) {
const jiti = await this.createJitiLoader();
configInput