diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..788c9aed
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,16 @@
+.git
+.idea
+.pytest_cache
+.ruff_cache
+__pycache__
+*.pyc
+*.pyo
+*.pyd
+.env
+.env.*
+tests/
+docs/
+notebooks/
+output/
+*.md
+!README.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ff01678e..82ad56c9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -35,8 +35,7 @@ If you are exploring HealthChain for use in your product or organization, or wan
**For substantial partnerships or integrations:**
- Shoot me an [email](mailto:jenniferjiangkells@gmail.com?subject=HealthChain)
-- Join our [weekly office hours](https://meet.google.com/zwh-douu-pky) (Thursdays 4.30pm - 5.30pm GMT) for direct Q&A
-- Join the [Discord](https://discord.gg/UQC6uAepUz) `#production-users` channel
+- Join the [Discord](https://discord.gg/UQC6uAepUz) `#production-users` channel for deployment and production-use questions
**For feature collaborations:**
Once we've aligned on a collaboration, we'll track it using GitHub issues with stage labels:
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..87172247
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,48 @@
+# HealthChain application Dockerfile
+#
+# Usage:
+# Build: docker build -t my-healthcare-app .
+# Run: docker run -p 8000:8000 --env-file .env my-healthcare-app
+#
+# Required environment variables (set in .env or pass via -e):
+# APP_MODULE Python module path to your app, e.g. "myapp:app" (default: "app:app")
+#
+# FHIR source credentials (if connecting to Epic/Cerner):
+# FHIR_BASE_URL, CLIENT_ID, CLIENT_SECRET or CLIENT_SECRET_PATH
+#
+# See docs: https://dotimplement.github.io/HealthChain/reference/gateway/gateway/
+
+FROM python:3.11-slim
+
+# Keeps Python from buffering stdout/stderr
+ENV PYTHONUNBUFFERED=1 \
+ PYTHONDONTWRITEBYTECODE=1 \
+ APP_MODULE=app:app \
+ PORT=8000
+
+WORKDIR /app
+
+# Install system dependencies needed by lxml and spaCy
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ gcc \
+ g++ \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install healthchain from PyPI
+RUN pip install --no-cache-dir healthchain
+
+# Install any additional dependencies your application needs
+# (copy requirements first to leverage Docker layer caching)
+COPY requirements.txt* ./
+RUN if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi
+
+# Copy application code
+COPY . .
+
+# Run as non-root user
+RUN useradd -m appuser && chown -R appuser /app
+USER appuser
+
+EXPOSE $PORT
+
+CMD uvicorn $APP_MODULE --host 0.0.0.0 --port $PORT
diff --git a/README.md b/README.md
index a004dda6..46318128 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
-HealthChain is an open-source developer framework to build healthcare AI applications with native protocol understanding. Skip months of custom integration with **built-in FHIR support**, **real-time EHR connectivity**, and **production-ready deployment** - all in Python.
+HealthChain is an open-source SDK for production-ready healthcare AI. Skip months of custom integration work with **built-in FHIR support**, **real-time EHR connectivity**, and **deployment tooling for healthcare AI/ML systems** โ all in Python.
@@ -132,6 +132,7 @@ HealthChain understands healthcare protocols and data formats natively, so you d
- **Automatic validation** - Type-safe FHIR models prevent broken healthcare data
- **Built-in NLP support** - Extract structured data from clinical notes, output as FHIR
- **Developer experience** - Modular and extensible architecture works across any EHR system
+- **Production-ready** - OAuth2-based authentication, Dockerized deployment, and structured audit hooks for real-world healthcare environments
## ๐ Recognition & Community
@@ -143,7 +144,20 @@ HealthChain understands healthcare protocols and data formats natively, so you d
## ๐ค Partnerships & Production Use
-Exploring HealthChain for your product or organization? Drop in our [weekly office hours](https://meet.google.com/zwh-douu-pky) (Thursdays 4.30pm - 5.30pm GMT) or [get in touch](mailto:jenniferjiangkells@gmail.com) to discuss integrations, pilots, or collaborations.
+Exploring HealthChain for your product or organization? [Get in touch](mailto:jenniferjiangkells@gmail.com) to discuss integrations, pilots, or collaborations, or join our [Discord](https://discord.gg/UQC6uAepUz) to connect with the community.
+
+## Create a New HealthChain App
+
+```bash
+# Scaffold a new project
+healthchain new my-app
+cd my-app
+
+# Run locally
+healthchain serve
+```
+
+See the [CLI reference](https://dotimplement.github.io/HealthChain/cli/) for all commands.
## Usage Examples
@@ -230,9 +244,10 @@ client.save_results("./output/")
## ๐ฃ๏ธ Road Map
- [ ] ๐ Data provenance and observability
-- [ ] ๐ Production security and compliance (Authentication, audit logging, HIPAA)
-- [ ] ๐ HL7v2 parsing, FHIR profile conversion and OMOP mapping support
-- [ ] ๐ Enhanced deployment support (Docker, Kubernetes, telemetry)
+- [ ] ๐ Production security and compliance โ enhanced authentication, audit logging, and HIPAA-aligned controls (encryption, access logging, configuration patterns)
+- [ ] ๐ HL7v2 parsing, FHIR profile conversion, and OMOP mapping
+- [ ] ๐งพ Da Vinci CRD/DTR/PAS prior authorization workflows
+- [ ] ๐ Kubernetes deployment and telemetry integration
- [ ] ๐ Model performance monitoring with MLFlow integration
- [ ] ๐ค MCP server integration
diff --git a/docs/cli.md b/docs/cli.md
new file mode 100644
index 00000000..de36fa8f
--- /dev/null
+++ b/docs/cli.md
@@ -0,0 +1,94 @@
+# CLI Reference
+
+HealthChain ships with a CLI to help you scaffold, run, and customize projects.
+
+```bash
+healthchain --help
+```
+
+---
+
+## `healthchain new`
+
+Scaffold a new project directory with everything you need to get started.
+
+```bash
+healthchain new my-app
+```
+
+Creates:
+
+```
+my-app/
+โโโ app.py # your application entry point
+โโโ .env.example # FHIR credential template โ copy to .env and fill in
+โโโ requirements.txt # add extra dependencies here
+โโโ Dockerfile
+โโโ .dockerignore
+```
+
+---
+
+## `healthchain serve`
+
+Start your app locally with uvicorn.
+
+```bash
+healthchain serve # defaults to app:app on port 8000
+healthchain serve app:app
+healthchain serve app:app --port 8080
+healthchain serve app:app --host 127.0.0.1 --port 8080
+```
+
+The `app_module` argument is the Python import path to your FastAPI app instance โ `:`. If your app is defined as `app = HealthChainAPI()` in `app.py`, the default `app:app` works as-is.
+
+To run in Docker instead:
+
+```bash
+docker build -t my-app .
+docker run -p 8000:8000 --env-file .env my-app
+```
+
+---
+
+## `healthchain eject-templates`
+
+Copy the built-in interop templates into your project so you can customize them.
+
+```bash
+healthchain eject-templates ./my_configs
+```
+
+Only needed if you're using the [InteropEngine](reference/interop/interop.md) and want to customize FHIRโCDA conversion beyond the defaults. After ejecting:
+
+```python
+from healthchain.interop import create_interop
+
+engine = create_interop(config_dir="./my_configs")
+```
+
+See [Interoperability](reference/interop/interop.md) for details.
+
+---
+
+## Typical workflow
+
+```bash
+# 1. Scaffold a new project
+healthchain new my-cds-service
+cd my-cds-service
+
+# 2. Build your app in app.py
+# See https://dotimplement.github.io/HealthChain/cookbook/ for examples
+
+# 3. Set credentials
+cp .env.example .env
+# edit .env with your FHIR_BASE_URL, CLIENT_ID, CLIENT_SECRET
+
+# 4. Run locally
+healthchain serve
+
+# 5. Ship it
+docker build -t my-cds-service .
+docker run -p 8000:8000 --env-file .env my-cds-service
+```
diff --git a/docs/community/index.md b/docs/community/index.md
index 7680a8fd..0a9dfbb1 100644
--- a/docs/community/index.md
+++ b/docs/community/index.md
@@ -3,7 +3,6 @@
## Get Involved
- **Discord**: Join our [Discord community](https://discord.gg/UQC6uAepUz) for questions, discussions, and connecting with other users
-- **Office Hours**: Weekly office hours every Thursday 4:30pm - 5:30pm GMT ([join here](https://meet.google.com/zwh-douu-pky))
- **GitHub Discussions**: For exploratory ideas and architecture discussions
- **Contributing**: See [CONTRIBUTING.md](https://github.com/dotimplement/HealthChain/blob/main/CONTRIBUTING.md) for full guidelines
diff --git a/docs/index.md b/docs/index.md
index da431181..65b5505d 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -53,7 +53,7 @@ HealthChain is an open-source Python toolkit that streamlines productionizing he
## Getting Started with Healthcare AI
-HealthChain provides the missing middleware layer between healthcare systems and modern AI/ML development. Whether you're building clinical decision support tools, processing medical documents, or creating multi-system integrations, these docs will guide you through:
+HealthChain is production-ready healthcare AI infrastructure: built-in FHIR support, real-time EHR connectivity, and deployment tooling for healthcare AI/ML systems. Skip months of custom integration work. Whether you're building clinical decision support tools, processing medical documents, or creating multi-system integrations, these docs will guide you through:
- **๐ง Core concepts** - Understand FHIR resources, pipelines, and gateway patterns
- **๐ Real examples** - Step-by-step tutorials for common healthcare AI use cases
diff --git a/docs/reference/interop/configuration.md b/docs/reference/interop/configuration.md
index 5eb66304..e4548203 100644
--- a/docs/reference/interop/configuration.md
+++ b/docs/reference/interop/configuration.md
@@ -27,8 +27,8 @@ engine = create_interop(config_dir="/path/to/custom/configs")
To create editable configuration templates:
```bash
-# Create customizable config templates
-healthchain init-configs ./my_configs
+# Eject built-in templates for customization
+healthchain eject-templates ./my_configs
# Then use them in your code
engine = create_interop(config_dir="./my_configs")
diff --git a/docs/reference/interop/engine.md b/docs/reference/interop/engine.md
index 903dabe5..67d79509 100644
--- a/docs/reference/interop/engine.md
+++ b/docs/reference/interop/engine.md
@@ -43,10 +43,10 @@ engine = create_interop(validation_level="warn", environment="production")
> **๐ก Tip:**
-> To create editable configuration templates, run:
+> To eject the built-in templates for customization, run:
>
> ```bash
-> healthchain init-configs ./my_configs
+> healthchain eject-templates ./my_configs
> ```
> This will create a `my_configs` directory with editable default configuration templates.
diff --git a/docs/reference/interop/experimental.md b/docs/reference/interop/experimental.md
index ba8793db..cc757e69 100644
--- a/docs/reference/interop/experimental.md
+++ b/docs/reference/interop/experimental.md
@@ -28,7 +28,7 @@ This page tracks templates that are under development or have known issues. Use
1. Copy experimental files to your custom config:
```bash
- # After running: healthchain init-configs my_configs
+ # After running: healthchain eject-templates my_configs
cp dev-templates/allergies/allergies.yaml my_configs/interop/cda/sections/
cp dev-templates/allergies/allergy_*.liquid my_configs/templates/cda_fhir/
cp dev-templates/allergies/allergy_*.liquid my_configs/templates/fhir_cda/
diff --git a/docs/reference/interop/interop.md b/docs/reference/interop/interop.md
index 1c073e38..29918f8f 100644
--- a/docs/reference/interop/interop.md
+++ b/docs/reference/interop/interop.md
@@ -65,11 +65,11 @@ cda_document = engine.from_fhir(fhir_resources, dest_format="cda")
```
### Custom Configs
-The default templates that come with the package are limited to problems, medications, and notes and are meant for basic testing and prototyping. Use the `healthchain init-configs` command to create editable configuration templates:
+The default templates that come with the package are limited to problems, medications, and notes and are meant for basic testing and prototyping. Use the `healthchain eject-templates` command to create editable configuration templates:
```bash
-# Create editable configuration templates
-healthchain init-configs ./my_configs
+# Eject built-in templates for customization
+healthchain eject-templates ./my_configs
```
Then use the `config_dir` parameter to specify the path to your custom configs:
diff --git a/healthchain/cli.py b/healthchain/cli.py
index bf4577c6..f720367e 100644
--- a/healthchain/cli.py
+++ b/healthchain/cli.py
@@ -1,64 +1,219 @@
import argparse
import subprocess
+import sys
+from pathlib import Path
+_DOCKERFILE = """\
+# HealthChain application Dockerfile
+#
+# Usage:
+# Build: docker build -t my-healthcare-app .
+# Run: docker run -p 8000:8000 --env-file .env my-healthcare-app
+#
+# Required environment variables (set in .env or pass via -e):
+# APP_MODULE Python module path to your app, e.g. "myapp:app" (default: "app:app")
+#
+# FHIR source credentials (if connecting to Epic/Cerner):
+# FHIR_BASE_URL, CLIENT_ID, CLIENT_SECRET or CLIENT_SECRET_PATH
+#
+# See docs: https://dotimplement.github.io/HealthChain/reference/gateway/gateway/
-def run_file(filename):
- try:
- result = subprocess.run(["uv", "run", "python", filename], check=True)
- print(result.stdout)
- except subprocess.CalledProcessError as e:
- print(f"An error occurred while trying to run the file: {e}")
+FROM python:3.11-slim
+
+# Keeps Python from buffering stdout/stderr
+ENV PYTHONUNBUFFERED=1 \\
+ PYTHONDONTWRITEBYTECODE=1 \\
+ APP_MODULE=app:app \\
+ PORT=8000
+
+WORKDIR /app
+
+# Install system dependencies needed by lxml and spaCy
+RUN apt-get update && apt-get install -y --no-install-recommends \\
+ gcc \\
+ g++ \\
+ && rm -rf /var/lib/apt/lists/*
+
+# Install healthchain from PyPI
+RUN pip install --no-cache-dir healthchain
+
+# Install any additional dependencies your application needs
+# (copy requirements first to leverage Docker layer caching)
+COPY requirements.txt* ./
+RUN if [ -f requirements.txt ]; then pip install --no-cache-dir -r requirements.txt; fi
+
+# Copy application code
+COPY . .
+
+# Run as non-root user
+RUN useradd -m appuser && chown -R appuser /app
+USER appuser
+
+EXPOSE $PORT
+
+CMD uvicorn $APP_MODULE --host 0.0.0.0 --port $PORT
+"""
+
+_DOCKERIGNORE = """\
+.git
+.idea
+.pytest_cache
+.ruff_cache
+__pycache__
+*.pyc
+*.pyo
+*.pyd
+.env
+.env.*
+tests/
+docs/
+notebooks/
+output/
+*.md
+!README.md
+"""
+
+_ENV_EXAMPLE = """\
+# FHIR source credentials
+FHIR_BASE_URL=
+CLIENT_ID=
+CLIENT_SECRET=
+
+# For JWT assertion flow (e.g. Epic SMART on FHIR)
+# CLIENT_SECRET_PATH=/path/to/private_key.pem
+"""
+
+_REQUIREMENTS = "healthchain\n"
+
+_APP_PY = """\
+# Your HealthChain application goes here.
+# See https://dotimplement.github.io/HealthChain/ for examples.
+"""
-def init_configs(target_dir: str):
- """Initialize configuration templates for customization."""
+def new_project(name: str):
+ """Scaffold a new HealthChain project."""
+ project_dir = Path(name)
+
+ if project_dir.exists():
+ print(f"โ Directory '{name}' already exists.")
+ return
+
+ project_dir.mkdir()
+ (project_dir / "app.py").write_text(_APP_PY)
+ (project_dir / ".env.example").write_text(_ENV_EXAMPLE)
+ (project_dir / "requirements.txt").write_text(_REQUIREMENTS)
+ (project_dir / "Dockerfile").write_text(_DOCKERFILE)
+ (project_dir / ".dockerignore").write_text(_DOCKERIGNORE)
+
+ print(f"\nCreated project '{name}/'")
+ print(f" {name}/app.py")
+ print(f" {name}/.env.example")
+ print(f" {name}/requirements.txt")
+ print(f" {name}/Dockerfile")
+ print("\nNext steps:")
+ print(f" 1. Build your app in {name}/app.py")
+ print(" 2. Copy .env.example to .env and fill in your credentials")
+ print(f" 3. healthchain serve app:app (from inside {name}/)")
+ print(f" 4. docker build -t {name} {name}/")
+ print(f" 5. docker run -p 8000:8000 --env-file {name}/.env {name}")
+ print("\nUsing format conversion? Run: healthchain eject-templates ./configs")
+ print("See https://dotimplement.github.io/HealthChain/ for examples.")
+
+
+def eject_templates(target_dir: str):
+ """Eject built-in interop templates for customization."""
try:
from healthchain.interop import init_config_templates
target_path = init_config_templates(target_dir)
- print(f"\n๐ Success! Configuration templates created at: {target_path}")
- print("\n๐ Next steps:")
- print(" 1. Customize the configuration files in the created directory")
+ print(f"\nโ
Templates ejected to: {target_path}")
+ print("\nNext steps:")
+ print(" 1. Customize the templates in the created directory")
print(" 2. Use them in your code:")
print(" from healthchain.interop import create_interop")
print(f" engine = create_interop(config_dir='{target_dir}')")
- print("\n๐ See documentation for configuration options")
+ print(
+ "\nSee https://dotimplement.github.io/HealthChain/reference/interop/ for details."
+ )
except FileExistsError as e:
print(f"โ Error: {str(e)}")
- print("๐ก Tip: Choose a different directory name or remove the existing one")
+ print("๐ก Choose a different directory name or remove the existing one.")
except Exception as e:
- print(f"โ Error initializing configs: {str(e)}")
- print("๐ก Tip: Make sure HealthChain is properly installed")
+ print(f"โ Error ejecting templates: {str(e)}")
+ print("๐ก Make sure HealthChain is properly installed.")
+
+
+def serve(app_module: str, host: str, port: int):
+ """Start a HealthChain app with uvicorn."""
+ try:
+ subprocess.run(
+ [
+ sys.executable,
+ "-m",
+ "uvicorn",
+ app_module,
+ "--host",
+ host,
+ "--port",
+ str(port),
+ ],
+ check=True,
+ )
+ except subprocess.CalledProcessError as e:
+ print(f"โ Server error: {e}")
+ except KeyboardInterrupt:
+ pass
def main():
parser = argparse.ArgumentParser(description="HealthChain command-line interface")
subparsers = parser.add_subparsers(dest="command", required=True)
- # Subparser for the 'run' command
- run_parser = subparsers.add_parser("run", help="Run a specified file")
- run_parser.add_argument("filename", type=str, help="The filename to run")
+ # Subparser for the 'new' command
+ new_parser = subparsers.add_parser("new", help="Scaffold a new HealthChain project")
+ new_parser.add_argument("name", type=str, help="Project name (creates a directory)")
+
+ # Subparser for the 'serve' command
+ serve_parser = subparsers.add_parser(
+ "serve", help="Start a HealthChain app with uvicorn"
+ )
+ serve_parser.add_argument(
+ "app_module",
+ type=str,
+ nargs="?",
+ default="app:app",
+ help="Module path to your app (default: app:app)",
+ )
+ serve_parser.add_argument(
+ "--host", type=str, default="0.0.0.0", help="Host (default: 0.0.0.0)"
+ )
+ serve_parser.add_argument(
+ "--port", type=int, default=8000, help="Port (default: 8000)"
+ )
- # Subparser for the 'init-configs' command
- init_parser = subparsers.add_parser(
- "init-configs",
- help="Initialize configuration templates for interop customization",
+ # Subparser for the 'eject-templates' command
+ eject_parser = subparsers.add_parser(
+ "eject-templates",
+ help="Eject built-in interop templates for customization",
)
- init_parser.add_argument(
+ eject_parser.add_argument(
"target_dir",
type=str,
nargs="?",
default="./healthchain_configs",
- help="Directory to create configuration templates (default: ./healthchain_configs)",
+ help="Directory to eject templates into (default: ./healthchain_configs)",
)
args = parser.parse_args()
- if args.command == "run":
- run_file(args.filename)
- elif args.command == "init-configs":
- init_configs(args.target_dir)
+ if args.command == "new":
+ new_project(args.name)
+ elif args.command == "serve":
+ serve(args.app_module, args.host, args.port)
+ elif args.command == "eject-templates":
+ eject_templates(args.target_dir)
if __name__ == "__main__":
diff --git a/mkdocs.yml b/mkdocs.yml
index e84e4350..77d7c3ae 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -11,6 +11,7 @@ nav:
- Getting Started:
- Installation: installation.md
- Quickstart: quickstart.md
+ - CLI: cli.md
- Licence: distribution.md
- Tutorials:
- tutorials/index.md
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 9d513865..d1448e47 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -4,7 +4,7 @@
import subprocess
from unittest.mock import patch
-from healthchain.cli import init_configs, run_file, main
+from healthchain.cli import eject_templates, serve, main
@pytest.mark.parametrize(
@@ -14,27 +14,27 @@
FileExistsError("Directory already exists"),
[
"โ Error: Directory already exists",
- "๐ก Tip: Choose a different directory name or remove the existing one",
+ "๐ก Choose a different directory name or remove the existing one",
],
),
(
Exception("Something went wrong"),
[
- "โ Error initializing configs: Something went wrong",
- "๐ก Tip: Make sure HealthChain is properly installed",
+ "โ Error ejecting templates: Something went wrong",
+ "๐ก Make sure HealthChain is properly installed",
],
),
],
)
@patch("healthchain.interop.init_config_templates")
-def test_init_configs_error_handling_provides_helpful_guidance(
+def test_eject_templates_error_handling_provides_helpful_guidance(
mock_init_templates, error, expected_messages
):
- """init_configs provides helpful error messages and guidance when template creation fails."""
+ """eject_templates provides helpful error messages and guidance when template creation fails."""
mock_init_templates.side_effect = error
with patch("builtins.print") as mock_print:
- init_configs("./test_configs")
+ eject_templates("./test_configs")
# Verify helpful error messages are displayed
for expected_msg in expected_messages:
@@ -42,50 +42,59 @@ def test_init_configs_error_handling_provides_helpful_guidance(
@patch("healthchain.interop.init_config_templates")
-def test_init_configs_success_provides_usage_instructions(mock_init_templates):
- """init_configs provides clear usage instructions when successful."""
+def test_eject_templates_success_provides_usage_instructions(mock_init_templates):
+ """eject_templates provides clear usage instructions when successful."""
target_dir = "./test_configs"
mock_init_templates.return_value = target_dir
with patch("builtins.print") as mock_print:
- init_configs(target_dir)
+ eject_templates(target_dir)
# Verify success message and usage instructions are provided
print_output = " ".join(str(call) for call in mock_print.call_args_list)
- assert "๐ Success!" in print_output
+ assert "โ
Templates ejected to:" in print_output
assert "create_interop(config_dir=" in print_output
- assert "๐ Next steps:" in print_output
+ assert "Next steps:" in print_output
@patch("subprocess.run")
-def test_run_file_handles_execution_errors_gracefully(mock_run):
- """run_file provides clear error message when script execution fails."""
- mock_run.side_effect = subprocess.CalledProcessError(1, "uv")
+def test_serve_handles_execution_errors_gracefully(mock_run):
+ """serve provides clear error message when server fails to start."""
+ mock_run.side_effect = subprocess.CalledProcessError(1, "uvicorn")
with patch("builtins.print") as mock_print:
- run_file("failing_script.py")
+ serve("app:app", "0.0.0.0", 8000)
# Verify error message is informative
error_message = mock_print.call_args[0][0]
- assert "An error occurred while trying to run the file:" in error_message
+ assert "โ Server error:" in error_message
@pytest.mark.parametrize(
"args,expected_call",
[
- (["healthchain", "run", "test.py"], ("run_file", "test.py")),
- (["healthchain", "init-configs", "my_configs"], ("init_configs", "my_configs")),
- (["healthchain", "init-configs"], ("init_configs", "./healthchain_configs")),
+ (
+ ["healthchain", "serve", "test.py:app"],
+ ("serve", ("test.py:app", "0.0.0.0", 8000)),
+ ),
+ (
+ ["healthchain", "eject-templates", "my_configs"],
+ ("eject_templates", ("my_configs",)),
+ ),
+ (
+ ["healthchain", "eject-templates"],
+ ("eject_templates", ("./healthchain_configs",)),
+ ),
],
)
def test_main_routes_commands_correctly(args, expected_call):
"""Main function correctly routes CLI commands to appropriate handlers."""
- function_name, expected_arg = expected_call
+ function_name, expected_args = expected_call
with patch(f"healthchain.cli.{function_name}") as mock_function:
with patch("sys.argv", args):
main()
- mock_function.assert_called_once_with(expected_arg)
+ mock_function.assert_called_once_with(*expected_args)
def test_main_requires_command_argument():