#!/usr/bin/env python3 """ DSS-CLI - A command-line interface for the DSS Engine This script provides a direct, scriptable interface to the core functionalities of the DSS analysis and context engine. It is designed for use in CI/CD pipelines and other automated workflows. """ import argparse import json import os import sys from pathlib import Path # Ensure the script can find the 'dss' module # This adds the parent directory of 'dss-mvp1' to the Python path # Assuming the script is run from the project root, this will allow `from dss...` imports sys.path.insert(0, str(Path(__file__).parent.parent)) try: from dss.analyze.project_analyzer import run_project_analysis, export_project_context from dss.project.manager import ProjectManager from dss import StorybookScanner, StoryGenerator, ThemeGenerator from dss.project.figma import FigmaProjectSync except ImportError as e: print(f"Error: Could not import DSS modules. Make sure dss-mvp1 is in the PYTHONPATH.", file=sys.stderr) print(f"Import error: {e}", file=sys.stderr) sys.exit(1) def main(): """Main function to parse arguments and dispatch commands.""" parser = argparse.ArgumentParser( description="DSS Command Line Interface for project analysis and context management." ) subparsers = parser.add_subparsers(dest="command", required=True, help="Available commands") # ========================================================================= # 'analyze' command # ========================================================================= analyze_parser = subparsers.add_parser( "analyze", help="Run a deep analysis of a project and save the results to .dss/analysis_graph.json" ) analyze_parser.add_argument( "--project-path", required=True, help="The root path to the project directory to be analyzed." ) # ========================================================================= # 'export-context' command # ========================================================================= export_parser = subparsers.add_parser( "export-context", help="Export the comprehensive project context as a JSON object to stdout." ) export_parser.add_argument( "--project-path", required=True, help="The path to the project directory." ) # ========================================================================= # 'add-figma-file' command # ========================================================================= add_figma_parser = subparsers.add_parser( "add-figma-file", help="Link a Figma file to a DSS project." ) add_figma_parser.add_argument( "--project-path", required=True, help="The path to the DSS project directory." ) add_figma_parser.add_argument( "--file-key", required=True, help="The file key of the Figma file (from the URL)." ) add_figma_parser.add_argument( "--file-name", required=True, help="A human-readable name for the Figma file." ) # ========================================================================= # 'setup-storybook' command # ========================================================================= storybook_parser = subparsers.add_parser( "setup-storybook", help="Scan, generate, or configure Storybook for a project." ) storybook_parser.add_argument( "--project-path", required=True, help="The path to the DSS project directory." ) storybook_parser.add_argument( "--action", required=True, choices=["scan", "generate", "configure"], help="The Storybook action to perform." ) # ========================================================================= # 'sync-tokens' command # ========================================================================= sync_parser = subparsers.add_parser( "sync-tokens", help="Synchronize design tokens from the linked Figma file(s)." ) sync_parser.add_argument( "--project-path", required=True, help="The path to the DSS project directory." ) sync_parser.add_argument( "--figma-token", help="Your Figma personal access token. If not provided, it will try to use the FIGMA_TOKEN environment variable." ) args = parser.parse_args() # --- Command Dispatch --- project_path = Path(args.project_path).resolve() if not project_path.is_dir(): print(f"Error: Provided project path is not a valid directory: {project_path}", file=sys.stderr) sys.exit(1) try: if args.command == "analyze": result = run_project_analysis(str(project_path)) print(f"Analysis complete. Graph saved to {project_path / '.dss' / 'analysis_graph.json'}") # Optionally print a summary to stdout summary = { "status": "success", "nodes_created": len(result.get("nodes", [])), "links_created": len(result.get("links", [])), } print(json.dumps(summary, indent=2)) elif args.command == "export-context": result = export_project_context(str(project_path)) # Print the full context to stdout print(json.dumps(result, indent=2)) elif args.command == "add-figma-file": manager = ProjectManager() try: project = manager.load(project_path) except FileNotFoundError: print(f"Error: No 'ds.config.json' found at {project_path}. Is this a valid DSS project?", file=sys.stderr) sys.exit(1) manager.add_figma_file( project=project, file_key=args.file_key, file_name=args.file_name ) print(f"Successfully added Figma file '{args.file_name}' to project '{project.config.name}'.") elif args.command == "setup-storybook": action = args.action print(f"Running Storybook setup with action: {action}...") if action == "scan": scanner = StorybookScanner(project_path) result = scanner.scan() print(json.dumps(result, indent=2)) elif action == "generate": generator = StoryGenerator(project_path) result = generator.generate() print(f"Successfully generated {len(result)} new stories.") elif action == "configure": theme_gen = ThemeGenerator(project_path) result = theme_gen.generate() print(f"Storybook theme configured at {result.get('theme_file')}") print("Storybook setup complete.") elif args.command == "sync-tokens": manager = ProjectManager() try: project = manager.load(project_path) except FileNotFoundError: print(f"Error: No 'ds.config.json' found at {project_path}. Is this a valid DSS project?", file=sys.stderr) sys.exit(1) print("Synchronizing tokens from Figma...") manager.sync(project, figma_token=args.figma_token) print("Token synchronization complete.") except Exception as e: print(json.dumps({"success": False, "error": str(e)}), file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()