text: import ast
  from pathlib import Path
  from typing import List, Optional, Tuple
  
  import typer
  from flexlate.template_data import TemplateData
  
  from flexlate_dev import get_version
  from flexlate_dev.cli_validators import parse_data_from_str
  from flexlate_dev.publish import publish_all_templates, publish_template
  from flexlate_dev.server import serve_template
  from flexlate_dev.styles import INFO_STYLE, print_styled
  
  cli = typer.Typer()
  
  TEMPLATE_PATH_DOC = "Location of template, can be a local path or URL"
  NO_INPUT_DOC = "Whether to proceed without any input from the user"
  NO_AUTO_COMMIT_DOC = (
      "Whether to skip automatically committing manual changes in the generated project"
  )
  CONFIG_PATH_DOC = "The location of the flexlate-dev configuration file to use"
  SAVE_DOC = "Whether to save the config file with any changes from the run such as answering project questions"
  RUN_CONFIG_NAME_DOC = "The name of the run configuration to use"
  DATA_DOC = (
      "The default data to use for the template, overrides the config file. "
      'Must be a dictionary, e.g. --data \'{"foo": "bar"}\''
  )
  FOLDER_NAME_DOC = "The name of the folder to create for the project"
  
  TEMPLATE_PATH_OPTION = typer.Option(
      Path("."),
      "--template",
      "-t",
      help=TEMPLATE_PATH_DOC,
  )
  NO_INPUT_OPTION = typer.Option(
      False, "--no-input", "-n", show_default=False, help=NO_INPUT_DOC
  )
  NO_AUTO_COMMIT_OPTION = typer.Option(
      False, "--no-auto-commit", "-a", show_default=False, help=NO_AUTO_COMMIT_DOC
  )
  CONFIG_PATH_OPTION = typer.Option(
      None, "--config", "-c", show_default=False, help=CONFIG_PATH_DOC
  )
  SAVE_OPTION = typer.Option(False, "--save", "-s", show_default=False, help=SAVE_DOC)
  DATA_OPTION = typer.Option(None, "--data", "-d", show_default=False, help=DATA_DOC)
  FOLDER_NAME_OPTION = typer.Option(
      None, "--folder-name", "-f", show_default=False, help=FOLDER_NAME_DOC
  )
  RUN_CONFIG_ARGUMENT = typer.Argument(None, help=RUN_CONFIG_NAME_DOC)
  
  
  @cli.callback(invoke_without_command=True)
  def pre_execute(
      version: bool = typer.Option(
          False,
          "--version",
          "-v",
          show_default=False,
          help="Show flexlate-dev and flexlate version, then exit",
      )
  ):
      # Support printing version and then existing with dfxt --version
      if version:
          version_number = get_version.get_flexlate_dev_version()
          flexlate_version = get_version.get_flexlate_version()
          message = "\n".join(
              [
                  f"flexlate-dev: {version_number}",
                  f"flexlate: {flexlate_version}",
              ]
          )
          print_styled(message, INFO_STYLE)
          exit(0)
  
  
  @cli.command(name="serve")
  def serve(
      run_config: Optional[str] = RUN_CONFIG_ARGUMENT,
      out_path: Optional[Path] = typer.Option(
          None,
          "--out",
          "-o",
          help="Optional location to serve built template to, defaults to a temporary directory",
      ),
      template_path: Path = TEMPLATE_PATH_OPTION,
      no_input: bool = NO_INPUT_OPTION,
      no_auto_commit: bool = NO_AUTO_COMMIT_OPTION,
      config_path: Optional[Path] = CONFIG_PATH_OPTION,
      save: bool = SAVE_OPTION,
      data: Optional[str] = DATA_OPTION,
      folder_name: Optional[str] = FOLDER_NAME_OPTION,
  ):
      """
      Run a development server with auto-reloading to see rendered output of a template
      """
      if data is not None:
          parsed_data = parse_data_from_str(data)
      else:
          parsed_data = None
      serve_template(
          run_config,
          template_path,
          out_path,
          no_input=no_input,
          auto_commit=not no_auto_commit,
          config_path=config_path,
          save=save,
          data=parsed_data,
          folder_name=folder_name,
      )
  
  
  @cli.command(name="publish")
  def publish(
      out_path: Path = typer.Argument(
          ...,
          help="Location to publish built template to",
      ),
      run_config: Optional[str] = RUN_CONFIG_ARGUMENT,
      template_path: Path = TEMPLATE_PATH_OPTION,
      config_path: Optional[Path] = CONFIG_PATH_OPTION,
      no_input: bool = NO_INPUT_OPTION,
      save: bool = SAVE_OPTION,
      data: Optional[str] = DATA_OPTION,
      folder_name: Optional[str] = FOLDER_NAME_OPTION,
  ):
      """
      Sync rendered output of a template
      """
      publish_template(
          template_path,
          out_path,
          run_config_name=run_config,
          config_path=config_path,
          save=save,
          no_input=no_input,
          data=data,
          folder_name=folder_name,
      )
  
  
  @cli.command(name="publish-all")
  def publish_all(
      out_path: Path = typer.Argument(
          ...,
          help="Location to publish built templates to",
      ),
      template_path: Path = TEMPLATE_PATH_OPTION,
      config_path: Optional[Path] = CONFIG_PATH_OPTION,
      always_include_default: bool = typer.Option(
          False,
          "--always-include-default",
          "-a",
          show_default=False,
          help="Always include the default run configuration even when other "
          "run configurations are defined. Default: Only use the default "
          "config when no other run configurations are defined.",
      ),
      exclude: Optional[List[str]] = typer.Option(
          None,
          "--exclude",
          "-e",
          help="Exclude run configurations by name. Can be specified multiple "
          "times to exclude multiple run configurations.",
      ),
      no_input: bool = NO_INPUT_OPTION,
      save: bool = SAVE_OPTION,
      data: Optional[str] = DATA_OPTION,
  ):
      """
      Sync rendered output of a template for all run configurations in the config file
      """
      publish_all_templates(
          template_path,
          out_path,
          config_path=config_path,
          save=save,
          no_input=no_input,
          always_include_default=always_include_default,
          exclude=exclude,
          data=data,
      )
  
  
  if __name__ == "__main__":
      cli()
  