CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-recast

JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator

Pending
Overview
Eval results
Files

cli-interface.mddocs/

Command Line Interface

Convenient command-line interface for running transformations on files directly from the shell or within scripts.

Capabilities

Run Function

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);
  }
});

Command Line Usage Patterns

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.js

File Processing Workflow

The run function handles the complete file processing pipeline:

  1. File Reading: Reads the file specified as the first command-line argument
  2. Parsing: Parses the file content into an AST using recast's parser
  3. Transformation: Calls the provided transformer function with the AST
  4. Printing: Converts the transformed AST back to code
  5. Output: Writes the result to stdout or custom writeback function

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);
  }
}

Advanced CLI Options

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);

Integration with Build Tools

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

docs

ast-manipulation.md

cli-interface.md

core-operations.md

index.md

parser-configuration.md

source-maps.md

tile.json