#!/usr/bin/env node
// Copyright (c) 2026 Chris Pressey, Cat's Eye Technologies.
//
// SPDX-License-Identifier: LicenseRef-MIT-X-Jaft
import { readFileSync } from "fs";
import { bless } from "concoctor";
import { concoctJaft } from "./jaftConcoctor.js";
function parseArgs(argv) {
const env = {};
let isFunDef = false;
let filenames = [];
for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a === "--expose") {
const spec = argv[i + 1];
if (!spec) continue;
const idx = spec.indexOf(":");
const name = spec.slice(0, idx).trim();
let expr = spec.slice(idx + 1).trim();
env[name] = bless(eval(expr));
i++;
} else if (a === "--fundef") {
isFunDef = true;
} else {
filenames.push(a);
}
}
return [filenames, isFunDef, env];
}
function main() {
const args = process.argv.slice(2);
const [filenames, isFunDef, env] = parseArgs(args);
if (filenames.length === 0) {
console.error("Error: No source file specified");
console.error("Usage: npm run jafti <source-file> -- {options}");
process.exit(1);
}
const sourceFile = filenames[0];
try {
const sourceCode =
(isFunDef ? "" : "() => ") + readFileSync(sourceFile, "utf-8");
const fn = concoctJaft(env, sourceCode);
let value = null;
if (isFunDef) {
const inputText = readFileSync(0, "utf8").trim();
value = JSON.parse(inputText);
}
const result = fn(value);
console.log(JSON.stringify(result));
} catch (error) {
if (error.code === "ENOENT") {
console.error(`Error: File not found: ${sourceFile}`);
} else if (error.message) {
console.error(`Error: ${error.message}`);
} else {
console.error("Error:", error);
}
process.exit(1);
}
}
main();