scripts.serialize_js_ts_ast

Reference › scripts › serialize_js_ts_ast

scripts/serialize_js_ts_ast.py is a Python wrapper for the Node.js parser serialize_js_ts_ast.js: it runs the parser over a JavaScript or TypeScript tree and writes the result as JSON, so JS and TS code can sit beside the Python AST. A human or the implementation scanner runs it (see scan_implementation and serialize_codebase_ast for the Python side). It has one subcommand, serialize, with required --source (the root directory to scan), --name (the project name) and --output (the JSON path), and --monorepo, which scans subdirectories as separate packages. main parses the arguments and _dispatch calls _serialize, which runs node. It needs Node.js on the machine.

At a glance

Source scripts/serialize_js_ts_ast.py
Lines of code 100
Classes 0
Functions 3
Imports (internal) none
Imported by none
Tests that import it none

Class diagram

No classes; see Functions.

Dependency diagram

No internal imports and no importers.

API

Functions

Function Signature Summary
main main(argv: list[str] | None = None) -> None
_dispatch _dispatch(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None
_serialize _serialize(args, script_path: Path | None = None) -> None

Source

Permalink: https://gitlab.com/MSamy/orchestrata-ultimate-architecture/-/blob/a4cbc2bdf/scripts/serialize_js_ts_ast.py

#!/usr/bin/env python3
"""
Python wrapper for serialize_js_ts_ast.js — runs the Node.js parser and
produces the same unified AST JSON schema as the Python serializer.

Usage::

    python scripts/serialize_js_ts_ast.py serialize \\
        --source ./src \\
        --name my-project \\
        --output plans/ast-myproject.json

    python scripts/serialize_js_ts_ast.py serialize \\
        --source ./packages \\
        --name my-monorepo \\
        --output plans/ast-monorepo.json \\
        --monorepo
"""

from __future__ import annotations

import argparse
import json
import subprocess
import sys
from pathlib import Path


def main(argv: list[str] | None = None) -> None:
    parser = argparse.ArgumentParser(
        description="Serialize JS/TS codebase AST to JSON (wraps Node.js parser)"
    )
    subp = parser.add_subparsers(dest="command", required=True)

    ser = subp.add_parser("serialize", help="Serialize a JS/TS codebase")
    ser.add_argument("--source", required=True, help="Root directory to scan")
    ser.add_argument("--name", required=True, help="Project name")
    ser.add_argument("--output", required=True, help="Output JSON path")
    ser.add_argument(
        "--monorepo", action="store_true", help="Scan subdirectories as packages"
    )

    args = parser.parse_args(argv)
    _dispatch(parser, args)


def _dispatch(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
    if args.command == "serialize":
        _serialize(args)
    else:
        parser.print_help()
        sys.exit(1)


def _serialize(args, script_path: Path | None = None) -> None:
    script = (
        script_path
        if script_path is not None
        else Path(__file__).resolve().parent / "serialize_js_ts_ast.js"
    )
    if not script.exists():
        print(f"Error: Node.js script not found: {script}", file=sys.stderr)
        sys.exit(1)

    cmd = [
        "node",
        str(script),
        "--source",
        args.source,
        "--name",
        args.name,
        "--output",
        args.output,
    ]
    if args.monorepo:
        cmd.append("--monorepo")

    result = subprocess.run(cmd, capture_output=True, text=True)

    if result.stderr:
        for line in result.stderr.strip().split("\n"):
            print(line, file=sys.stderr)

    if result.returncode != 0:
        sys.exit(result.returncode)

    # Validate the output is valid JSON
    output_path = Path(args.output)
    try:
        with open(output_path) as f:
            json.load(f)
    except (json.JSONDecodeError, FileNotFoundError) as e:
        print(f"Error: Invalid JSON output: {e}", file=sys.stderr)
        sys.exit(1)

    print(f"✓ AST written to {output_path}")


if __name__ == "__main__":
    main()