JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator
—
Convenient command-line interface for running transformations on files directly from the shell or within scripts.
Execute transformations on files using a transformer function, typically used for command-line tools and scripts.
/**
* Run a transformer function on files from command line arguments
* @param transformer - Function that transforms AST and calls callback with result
* @param options - Optional configuration including writeback function
*/
function run(transformer: Transformer, options?: RunOptions): void;
interface Transformer {
/** Transform AST and call callback with modified AST */
(ast: types.ASTNode, callback: (ast: types.ASTNode) => void): void;
}
interface RunOptions extends Options {
/** Custom function to handle output (default: write to stdout) */
writeback?(code: string): void;
}Usage Examples:
import { run, types, visit } from "recast";
// Transform arrow functions to regular functions
function transformer(ast: types.ASTNode, callback: (ast: types.ASTNode) => void) {
visit(ast, {
visitArrowFunctionExpression(path) {
const node = path.value;
const func = types.builders.functionExpression(
null,
node.params,
types.builders.blockStatement([
types.builders.returnStatement(node.body)
])
);
path.replace(func);
this.traverse(path);
}
});
callback(ast);
}
// Run on command line argument file
// Usage: node my-transformer.js input.js
run(transformer);
// Run with custom writeback
run(transformer, {
writeback(code) {
require('fs').writeFileSync('output.js', code);
}
});The run function automatically handles file input and output for command-line tools.
Basic Pattern:
#!/usr/bin/env node
import { run, types, visit } from "recast";
function myTransformer(ast: types.ASTNode, callback: (ast: types.ASTNode) => void) {
// Your transformation logic here
visit(ast, {
// visitor methods
});
callback(ast);
}
// Run on file from command line argument
run(myTransformer);Usage from shell:
node my-transformer.js input.js > output.jsThe run function handles the complete file processing pipeline:
Error Handling:
function robustTransformer(ast: types.ASTNode, callback: (ast: types.ASTNode) => void) {
try {
// Your transformation logic
visit(ast, {
visitFunctionDeclaration(path) {
// Transform functions
this.traverse(path);
}
});
callback(ast);
} catch (error) {
console.error("Transformation failed:", error.message);
// Return original AST on error
callback(ast);
}
}Combining CLI functionality with parser and printer options.
import { run, Options } from "recast";
const transformOptions: Options = {
parser: require("recast/parsers/typescript"),
tabWidth: 2,
quote: "single"
};
function typeScriptTransformer(ast: types.ASTNode, callback: (ast: types.ASTNode) => void) {
// TypeScript-specific transformations
callback(ast);
}
run(typeScriptTransformer, transformOptions);Using the CLI interface within build processes and npm scripts.
package.json scripts:
{
"scripts": {
"transform": "node scripts/transformer.js",
"transform:all": "find src -name '*.js' -exec node scripts/transformer.js {} \\;"
}
}Build script example:
// scripts/transformer.js
import { run, types, visit } from "recast";
import fs from "fs";
import path from "path";
function buildTransformer(ast: types.ASTNode, callback: (ast: types.ASTNode) => void) {
visit(ast, {
visitCallExpression(path) {
// Replace debug calls in production
if (process.env.NODE_ENV === 'production') {
const node = path.value;
if (node.callee.name === 'debug') {
path.prune(); // Remove debug calls
return false;
}
}
this.traverse(path);
}
});
callback(ast);
}
run(buildTransformer, {
writeback(code) {
const inputFile = process.argv[2];
const outputFile = inputFile.replace(/\.js$/, '.min.js');
fs.writeFileSync(outputFile, code);
console.log(`Transformed ${inputFile} -> ${outputFile}`);
}
});Install with Tessl CLI
npx tessl i tessl/npm-recast