Skip to content

Simplify FastAPI fullstack template by include frontend code and a build script #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 34 commits into from
Nov 20, 2024

Conversation

leehuwuj
Copy link
Collaborator

@leehuwuj leehuwuj commented Nov 13, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Simplified commands for running development and production servers across various templates.
    • Added FrontendProxyMiddleware for enhanced request handling between FastAPI and frontend servers.
  • Improvements

    • Streamlined installation processes and error handling for backend and frontend setup.
    • Enhanced clarity in README templates for better user guidance.
  • Bug Fixes

    • Removed deprecated externalPort references to improve configuration consistency.
  • Documentation

    • Updated README files to reflect new commands and usage instructions for various projects.

Copy link

coderabbitai bot commented Nov 13, 2024

Walkthrough

The pull request introduces significant changes to the application setup process, particularly in how ports are referenced and the installation logic is executed. The externalPort parameter has been renamed to port, affecting multiple files. The backend installation is now always executed, while frontend installation is conditional based on the framework. Test files have been updated to reflect these changes, simplifying conditions for executing tests. Additionally, several utility functions and middleware have been added or modified to enhance the application's functionality and error handling.

Changes

File Change Summary
create-app.ts Renamed externalPort to port. Simplified backend installation logic and adjusted frontend directory creation. Removed commented-out README copy code.
e2e/shared/multiagent_template.spec.ts Updated appType assignment and modified conditions for skipping tests based on templateFramework.
e2e/shared/streaming_template.spec.ts Changed appType assignment and removed externalPort. Updated skip conditions for tests based on templateFramework.
e2e/utils.ts Made externalPort optional in RunCreateLlamaOptions. Simplified application start waiting logic to use only port.
helpers/devcontainer.ts Simplified renderDevcontainerContent logic by removing frontend parameter and streamlining command settings.
helpers/env-variables.ts Renamed externalPort to port in createBackendEnvFile function.
helpers/run-app.ts Updated return type of createProcess to Promise<void>, simplified runReflexApp and runApp functions for better error handling.
helpers/types.ts Renamed externalPort to port in InstallTemplateArgs.
helpers/typescript.ts Updated conditional logic for installing TypeScript dependencies.
index.ts Removed --external-port option; updated usage of --port. Refined handling of data sources.
questions/questions.ts Simplified framework selection logic in askProQuestions.
templates/types/streaming/fastapi/README-template.md Updated instructions for running the development server and production commands.
templates/types/streaming/fastapi/gitignore Added static/ directory to .gitignore.
templates/types/streaming/fastapi/main.py Modified middleware setup and static file mounting logic based on environment.
templates/types/streaming/fastapi/pyproject.toml Added new scripts for dev, prod, and build; added rich dependency.
templates/types/streaming/fastapi/run.py Introduced functions for managing frontend and backend servers, enhancing error handling.
e2e/python/resolve_dependencies.spec.ts Removed externalPort from options in tests.
e2e/shared/extractor_template.spec.ts Renamed frontendPort and backendPort to appPort. Removed externalPort from function call.
e2e/typescript/resolve_dependencies.spec.ts Removed externalPort from runCreateLlama function call.
questions/types.ts Modified QuestionResults type to include externalPort.
.changeset/popular-dryers-check.md Introduced a patch for improving deployment workflow for Python templates.
templates/types/streaming/fastapi/app/middlewares/frontend.py Added FrontendProxyMiddleware class for proxying requests to a frontend server.
templates/components/agents/python/blog/README-template.md Updated commands for running development and production servers.
templates/components/agents/python/financial_report/README-template.md Updated commands for running development and production servers.
templates/components/agents/python/form_filling/README-template.md Updated commands for running development and production servers.
templates/types/streaming/fastapi/app/config.py Added STATIC_DIR constant for dynamic static directory configuration.
templates/.gitignore Deleted .gitignore, removing entries for ignored files.
templates/README-fullstack.md Deleted README for fullstack project setup.

Possibly related PRs

Suggested reviewers

  • marcusschiesser

Poem

In the meadow, changes bloom,
Ports renamed, dispelling gloom.
With each line, the code does dance,
Simplified paths, a developer's chance.
From backend calls to frontend cheer,
A brighter setup, drawing near! 🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ae45d60 and 8079ba4.

📒 Files selected for processing (2)
  • templates/.gitignore (0 hunks)
  • templates/README-fullstack.md (0 hunks)
💤 Files with no reviewable changes (2)
  • templates/.gitignore
  • templates/README-fullstack.md

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

changeset-bot bot commented Nov 13, 2024

🦋 Changeset detected

Latest commit: 8079ba4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
create-llama Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@leehuwuj leehuwuj marked this pull request as ready for review November 19, 2024 02:16
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (16)
helpers/run-app.ts (1)

81-83: Consider refactoring template checks to improve maintainability

The condition template === "streaming" || template === "multiagent" appears multiple times. Refactoring this into a helper function or using an array of templates can enhance readability and make future updates easier.

Example refactor:

const templatesNeedingFrontend = ["streaming", "multiagent"];

if (frontend && templatesNeedingFrontend.includes(template)) {
  await buildFrontend(appPath, framework);
}
templates/types/streaming/fastapi/run.py (1)

1-5: Enhance code documentation and type safety

Consider adding:

  1. Type hints for function parameters and return values
  2. More detailed docstrings with parameters, returns, and raises sections
  3. Module-level docstring explaining the file's purpose

Add a module docstring and improve imports:

+"""
+Frontend build and development utilities for the FastAPI application.
+
+This module provides utilities for managing frontend dependencies,
+building the frontend application, and running the development server.
+"""
+
+from pathlib import Path
 import os
-
+from typing import Literal
 import rich
-
templates/types/streaming/fastapi/main.py (1)

47-48: Good API router setup with proper prefix.

The API router is correctly mounted with the "/api" prefix, following REST API best practices. This separation of API routes from static file routes is crucial for the frontend integration.

The placement of this line before the static file mounts is important. In FastAPI, route matching follows a first-come-first-served basis, so having the API routes registered first ensures they take precedence over any potential conflicts with static file paths.

helpers/types.ts (1)

99-99: Consider adding JSDoc documentation for the port parameter.

Adding documentation would help clarify the purpose and expected values of the port parameter.

Add JSDoc comments like this:

+  /** Port number for the application server. If not specified, a default port will be used. */
   port?: number;
e2e/shared/multiagent_template.spec.ts (2)

64-67: Add skip message for better test maintainability

The skip conditions are logically correct, but adding a descriptive skip message would improve test maintainability and debugging.

  test.skip(
    templatePostInstallAction !== "runApp" ||
      templateFramework === "express",
+   "Frontend title test is only applicable for non-Express frameworks with runApp action"
  );

76-79: Update skip message to include Express framework condition

The skip message should be updated to include all skip conditions for better clarity.

  test.skip(
    templatePostInstallAction !== "runApp" ||
      agents === "financial_report" ||
      agents === "form_filling" ||
      templateFramework === "express",
-   "Skip chat tests for financial report and form filling.",
+   "Skip chat tests for financial report, form filling, and Express framework.",
templates/types/streaming/fastapi/README-template.md (2)

24-28: Add language specification to code block

The code block should specify the shell language for proper syntax highlighting.

-```
+```shell
 poetry run build

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

---

`30-33`: **Add language specification to code block**

The code block should specify the shell language for proper syntax highlighting.

```diff
-```
+```shell
 poetry run dev

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

32-32: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>e2e/shared/streaming_template.spec.ts (2)</summary><blockquote>

`70-72`: **Add a descriptive skip message**

The skip condition logic is correct, but it would be helpful to add a message explaining why the test is skipped for express framework.

```diff
 test.skip(
   templatePostInstallAction !== "runApp" || templateFramework === "express",
+  "Frontend tests are skipped for express framework or when app is not running"
 );

80-82: Add a descriptive skip message

For consistency with the previous test, add a descriptive message explaining the skip condition.

 test.skip(
   templatePostInstallAction !== "runApp" || templateFramework === "express",
+  "Frontend message submission tests are skipped for express framework or when app is not running"
 );
create-app.ts (1)

95-104: Consider architectural improvements for frontend installation

Several suggestions for improvement:

  1. The .frontend directory being hidden might cause confusion. Consider making this configurable or using a visible directory.
  2. The tight coupling to "fastapi" framework limits extensibility. Consider making the frontend framework compatibility configurable.
  3. The hardcoded fallback port 8000 should be extracted to a constant or configuration.

Consider this refactor:

+ const DEFAULT_API_PORT = 8000;
+ const SUPPORTED_FRONTEND_FRAMEWORKS = ['fastapi'];  // Make extensible

- if (frontend && framework === "fastapi") {
+ if (frontend && SUPPORTED_FRONTEND_FRAMEWORKS.includes(framework)) {
    // install frontend
-   const frontendRoot = path.join(root, ".frontend");
+   const frontendRoot = path.join(root, "frontend");
    await makeDir(frontendRoot);
    await installTemplate({
      ...args,
      root: frontendRoot,
      framework: "nextjs",
-     customApiPath: `http://localhost:${port ?? 8000}/api/chat`,
+     customApiPath: `http://localhost:${port ?? DEFAULT_API_PORT}/api/chat`,
      backend: false,
    });
  }
e2e/utils.ts (1)

147-149: Consider validating for duplicate ports

While the implementation is clean, consider adding validation to prevent potential issues with duplicate port numbers. If port and externalPort are the same, it could lead to redundant waiting or misleading error messages.

Consider this improvement:

-    const portsToWait = externalPort ? [port, externalPort] : [port];
+    const portsToWait = externalPort && externalPort !== port ? [port, externalPort] : [port];
index.ts (1)

336-336: Add port number validation.

The port values are used without validation, which could lead to runtime errors if invalid values are provided.

Consider adding validation:

+ function validatePort(port: string | undefined): number {
+   if (!port) return 3000; // default port
+   const portNum = parseInt(port, 10);
+   if (isNaN(portNum) || portNum < 0 || portNum > 65535) {
+     throw new Error(`Invalid port number: ${port}`);
+   }
+   return portNum;
+ }

await createApp({
  ...answers,
  appPath: resolvedProjectPath,
  packageManager,
-  port: options.port,
+  port: validatePort(options.port),
});
helpers/typescript.ts (2)

Line range hint 351-386: Consider refactoring vector database dependencies logic.

The vector database specific sections in updatePackageJson follow a repetitive pattern. Consider extracting this into a separate configuration object or function for better maintainability.

+ const VECTOR_DB_DEPENDENCIES = {
+   pg: {
+     pg: "^8.12.0",
+     pgvector: "^0.2.0",
+   },
+   qdrant: {
+     "@qdrant/js-client-rest": "^1.11.0",
+   },
+   mongo: {
+     mongodb: "^6.7.0",
+   },
+   milvus: {
+     "@zilliz/milvus2-sdk-node": "^2.4.6",
+   },
+ };
+
   if (vectorDb) {
-    if (vectorDb === "pg") {
-      packageJson.dependencies = {
-        ...packageJson.dependencies,
-        pg: "^8.12.0",
-        pgvector: "^0.2.0",
-      };
-    }
-    if (vectorDb === "qdrant") {
-      packageJson.dependencies = {
-        ...packageJson.dependencies,
-        "@qdrant/js-client-rest": "^1.11.0",
-      };
-    }
-    if (vectorDb === "mongo") {
-      packageJson.dependencies = {
-        ...packageJson.dependencies,
-        mongodb: "^6.7.0",
-      };
-    }
-    if (vectorDb === "milvus") {
-      packageJson.dependencies = {
-        ...packageJson.dependencies,
-        "@zilliz/milvus2-sdk-node": "^2.4.6",
-      };
-    }
+    packageJson.dependencies = {
+      ...packageJson.dependencies,
+      ...VECTOR_DB_DEPENDENCIES[vectorDb],
+    };
   }

Line range hint 441-444: Enhance error handling in installTSDependencies.

The current error handling only logs and exits. Consider:

  1. Including the actual error message in the log
  2. Providing more context about what failed
-  await callPackageManager(packageManager, isOnline).catch((error) => {
-    console.error("Failed to install TS dependencies. Exiting...");
-    process.exit(1);
-  });
+  await callPackageManager(packageManager, isOnline).catch((error) => {
+    console.error(`Failed to install TS dependencies using ${packageManager}:`, error);
+    console.error("Please ensure you have the necessary permissions and network connectivity.");
+    process.exit(1);
+  });
questions/questions.ts (1)

136-136: Improve message clarity for frontend generation

The message could be more informative about the integration process. Consider adding details about what the frontend generation entails.

-        message: `Would you like to generate a ${styledNextJS} frontend for your FastAPI backend?`,
+        message: `Would you like to generate a ${styledNextJS} frontend that integrates with your FastAPI backend? This will create a separate frontend application.`,
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 00f0b3a and 78c7798.

📒 Files selected for processing (17)
  • create-app.ts (3 hunks)
  • e2e/shared/multiagent_template.spec.ts (3 hunks)
  • e2e/shared/streaming_template.spec.ts (3 hunks)
  • e2e/utils.ts (3 hunks)
  • helpers/devcontainer.ts (1 hunks)
  • helpers/env-variables.ts (2 hunks)
  • helpers/run-app.ts (3 hunks)
  • helpers/types.ts (1 hunks)
  • helpers/typescript.ts (1 hunks)
  • index.ts (1 hunks)
  • questions/questions.ts (2 hunks)
  • templates/.gitignore (1 hunks)
  • templates/types/streaming/fastapi/README-template.md (2 hunks)
  • templates/types/streaming/fastapi/gitignore (1 hunks)
  • templates/types/streaming/fastapi/main.py (1 hunks)
  • templates/types/streaming/fastapi/pyproject.toml (2 hunks)
  • templates/types/streaming/fastapi/run.py (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • templates/.gitignore
  • templates/types/streaming/fastapi/gitignore
🧰 Additional context used
📓 Path-based instructions (4)
templates/types/streaming/fastapi/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/main.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/pyproject.toml (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🪛 Markdownlint
templates/types/streaming/fastapi/README-template.md

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


32-32: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (21)
helpers/run-app.ts (2)

46-52: LGTM!

The buildFrontend function is implemented correctly and appropriately selects the package manager based on the framework.


78-95: LGTM!

The runApp function has been refactored correctly to handle asynchronous operations with proper error handling.

templates/types/streaming/fastapi/pyproject.toml (2)

21-21: LGTM: Rich library addition aligns with build script requirements

The addition of the rich library (^13.9.4) is appropriate for enhancing terminal output during frontend build and development processes. The version constraint allows for compatible updates while preventing breaking changes.


10-11: Verify the existence of referenced functions in run.py

The new script entries point to run:build and run:dev, which should be defined in a new run.py file.

✅ Verification successful

Functions referenced in pyproject.toml scripts are properly implemented

The verification confirms that both build() and dev() functions are correctly implemented in templates/types/streaming/fastapi/run.py:

  • build(): Handles frontend dependency installation, build process, and static file copying
  • dev(): Manages FastAPI app startup
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the referenced functions exist in run.py
# Expected: Find definitions of build and dev functions

# Search for run.py file
fd -t f "run.py$"

# Search for function definitions
ast-grep --pattern 'def build():
  $$$' 

ast-grep --pattern 'def dev():
  $$$'

Length of output: 2112

helpers/devcontainer.ts (1)

18-19: 🛠️ Refactor suggestion

Verify the build command execution timing and dependencies

The addition of poetry run build during container creation raises some concerns:

  1. Running the build during container creation might be premature as it requires all dependencies to be properly installed first.
  2. There's no error handling if the build fails, which could leave the container in an inconsistent state.

Let's verify the build command implementation and dependencies:

Consider these improvements:

-        ? "poetry install && poetry run build"
+        ? "poetry install && poetry run build || { echo 'Frontend build failed'; exit 1; }"

Consider moving the build step to a separate script that:

  1. Verifies all required dependencies are installed
  2. Sets up necessary environment variables
  3. Includes proper error handling and logging
  4. Can be executed independently of container creation

Would you like me to help create this build script?

templates/types/streaming/fastapi/main.py (2)

37-43: LGTM! The mount_static_files function enhancement looks good.

The addition of the html parameter with a default value of False maintains backward compatibility while enabling HTML file serving when needed. The implementation follows FastAPI best practices.

Let's verify the HTML file serving capability:

✅ Verification successful

The mount_static_files function enhancement is correctly implemented

The code analysis reveals that the function is properly used in three different scenarios:

  • Data files mounting at /api/files/data
  • Output files mounting at /api/files/output
  • Static files mounting at root / with html=True

The implementation is correct because:

  1. The html parameter is only enabled for the frontend static files at root
  2. The function maintains backward compatibility for data and output mounts
  3. The StaticFiles configuration follows FastAPI's recommended patterns

The absence of static/data directories in the verification is expected as this is a template file that will be populated during project instantiation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for HTML files in the static directory that will be served
# Expected: Find HTML files that would be served by the static file handler

# Search for HTML files in the static directory
fd -e html . static/

# Check if the static directory exists and is properly structured
if [ -d "static" ]; then
  echo "Static directory exists"
  ls -la static/
else
  echo "Warning: static directory not found"
fi

Length of output: 437


Script:

#!/bin/bash
# Let's check the codebase for static file mounting usage patterns
# and HTML file references to understand the implementation better

# Find all static file mounting calls
echo "Searching for static file mounting patterns..."
rg "mount_static_files|StaticFiles" -A 2 -B 2

# Look for HTML file references in the codebase
echo -e "\nSearching for HTML file references..."
rg -l "\.html"

# Check template structure
echo -e "\nChecking template structure..."
fd -t f . templates/types/streaming/fastapi/

Length of output: 3417


53-54: Verify directory structure for frontend static files.

The static file mounting structure looks good, with frontend files appropriately mounted at the root path with HTML support enabled.

Let's verify the directory structure and suggest potential improvements:

Consider adding error handling for cases where directories don't exist at runtime:

 def mount_static_files(directory, path, html=False):
     if os.path.exists(directory):
         logger.info(f"Mounting static files '{directory}' at '{path}'")
         app.mount(
             path,
             StaticFiles(directory=directory, check_dir=False, html=html),
             name=f"{directory}-static",
         )
+    else:
+        logger.warning(f"Directory '{directory}' does not exist, skipping mount at '{path}'")
✅ Verification successful

Let me verify if these directories are expected to be created at runtime or if they should exist in the repository by checking the codebase.


Based on the findings, I can now provide a final response. The missing directories are expected as they are created during the build/runtime process:

  1. The static directory is created when running poetry run build for the frontend UI
  2. The output directory is created at runtime for file outputs
  3. The DATA_DIR is configured through environment variables

The current implementation already has proper error handling by checking directory existence before mounting, so no changes are needed.

Static file mounting is correctly implemented with proper error handling

The current implementation in mount_static_files() already checks for directory existence before mounting, making it safe for cases where directories don't exist:

if os.path.exists(directory):
    logger.info(f"Mounting static files '{directory}' at '{path}'")
    app.mount(...)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify directory structure and content for static file mounting
# Expected: All directories should exist and contain appropriate files

# Check all mounted directories
echo "Checking data directory..."
if [ -d "$DATA_DIR" ]; then
  echo "✓ Data directory exists"
  ls -la "$DATA_DIR"
else
  echo "✗ Data directory missing"
fi

echo "Checking output directory..."
if [ -d "output" ]; then
  echo "✓ Output directory exists"
  ls -la output/
else
  echo "✗ Output directory missing"
fi

echo "Checking static directory..."
if [ -d "static" ]; then
  echo "✓ Static directory exists"
  echo "Frontend files:"
  fd . static/ -t f
else
  echo "✗ Static directory missing"
fi

Length of output: 437


Script:

#!/bin/bash
# Search for directory creation or initialization logic
echo "Searching for directory creation or initialization..."
rg -l "mkdir|makedirs|os\.path\.exists.*static|os\.path\.exists.*output" --type py

echo -e "\nChecking mount_static_files implementation..."
rg "def mount_static_files" -A 10

echo -e "\nChecking if static/output are gitignored..."
cat .gitignore || echo "No .gitignore found"

echo -e "\nChecking for build/setup instructions..."
fd "README|CONTRIBUTING" -e md -X cat {}

Length of output: 33218

e2e/shared/multiagent_template.spec.ts (1)

19-19: Verify architectural change in frontend handling

The change in appType assignment suggests a significant architectural shift where frontend is now associated with FastAPI instead of NextJS. This could have broader implications across the codebase.

✅ Verification successful

Let me gather more information about the frontend configuration by checking the test configuration and template setup.


Based on the comprehensive search results, I can now provide the final response:

Frontend configuration change is correct and intentional

The change in appType assignment is consistent with the codebase's architecture:

  • FastAPI templates now include frontend by default (--frontend), while NextJS has no explicit frontend flag (empty string)
  • This aligns with the application's structure where NextJS itself is a full-stack framework, while FastAPI requires an explicit frontend setup
  • The change is consistently implemented across multiple test files (streaming_template.spec.ts, multiagent_template.spec.ts)
  • The main application code in create-app.ts confirms this design where frontend installation is specifically handled for FastAPI: if (frontend && framework === "fastapi")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistency of frontend handling across the codebase

# Check for other instances of frontend type determination
rg -A 3 "appType.*=.*frontend" --type ts

# Look for related configuration in create-app
rg -A 5 "fastapi.*frontend" --type ts

Length of output: 2403


Script:

#!/bin/bash
# Check test configuration and template setup
# Look for template framework configuration
rg -B 2 -A 2 "templateFramework.*=.*" --type ts

# Check for any frontend-related configuration or setup
rg -B 2 -A 2 "frontend.*=.*" --type ts

# Look for NextJS related configurations
rg -B 2 -A 2 "nextjs" --type ts

Length of output: 18516

templates/types/streaming/fastapi/README-template.md (1)

59-59: LGTM!

Clear instructions for accessing either the chat UI or Swagger documentation based on frontend build status.

e2e/shared/streaming_template.spec.ts (2)

107-107: LGTM!

The port usage in the API endpoint is correctly updated, maintaining consistency with the port management changes.


25-25: ⚠️ Potential issue

Verify the logic for frontend flag assignment

The assignment of --frontend flag when templateFramework is "fastapi" seems counterintuitive, as FastAPI is a backend framework while Next.js is typically used for frontend. This could lead to incorrect test behavior.

Let's verify the intended behavior:

create-app.ts (2)

92-93: LGTM! Simplified backend installation logic

The unconditional backend installation simplifies the code flow and makes the behavior more predictable.


37-37: Verify documentation for breaking change

The parameter renaming from externalPort to port is a breaking change that could affect existing applications.

Let's verify the documentation and migration guide:

Also applies to: 83-83

✅ Verification successful

Based on the extensive git history and codebase analysis, I can now provide a definitive response about the parameter rename from externalPort to port:

Breaking change is properly handled and documented

The parameter rename from externalPort to port is actually part of a larger refactoring effort to simplify port handling across the codebase. The changes show:

  1. The parameter is still supported through backwards compatibility:
  • The CLI still accepts --external-port flag
  • The type definitions maintain support via optional externalPort parameter
  • The parameter is properly mapped in index.ts: port: options.externalPort
  1. The change is properly encapsulated:
  • Frontend installation uses the port parameter consistently
  • Backend services handle both port configurations
  • Test files have been updated to support both parameters
  1. No breaking changes introduced:
  • Existing code paths maintain compatibility
  • Default port values (3000/8000) are preserved
  • Port handling logic remains consistent
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if breaking change is documented

# Check for migration guide or changelog
fd -e md -e mdx . | xargs rg -i "externalPort.*port"

# Check for any remaining usages of externalPort
rg "externalPort"

Length of output: 1178


Script:

#!/bin/bash
# Let's check for recent changes related to this parameter rename
git log -p | rg -A 5 -B 5 "externalPort"

# Check the current state of create-app.ts
cat create-app.ts

# Look for any documentation or changelog files
fd "CHANGELOG|BREAKING|MIGRATION" -i

Length of output: 70785

e2e/utils.ts (2)

104-106: LGTM! Clean implementation of optional parameter handling

The conditional addition of externalPort to command arguments is well-implemented and handles the optional nature of the parameter correctly.


28-28: Verify the impact of optional externalPort on existing tests

Making externalPort optional is a breaking change that could affect existing tests.

Let's verify the usage in test files:

✅ Verification successful

The search results show that externalPort is actively used in multiple test files, particularly in:

  1. e2e/shared/multiagent_template.spec.ts
  2. e2e/shared/extractor_template.spec.ts
  3. e2e/python/resolve_dependencies.spec.ts
  4. e2e/typescript/resolve_dependencies.spec.ts

Let's verify how the externalPort is handled in the implementation to ensure the optional change doesn't break existing functionality:


Making externalPort optional is safe and properly handled

The implementation shows that externalPort is already properly guarded:

  • Command arguments only include --external-port when externalPort is provided
  • Port waiting logic correctly handles both cases with externalPort ? [port, externalPort] : [port]

Therefore, making it optional in the type definition aligns with the existing implementation and won't break existing tests since they all explicitly provide the port number.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all test files that use RunCreateLlamaOptions and check for externalPort usage

# Search for test files using RunCreateLlamaOptions
rg -l "RunCreateLlamaOptions" --glob "**/*.{test,spec}.{ts,tsx,js,jsx}"

# Search for direct usage of externalPort in test files
rg "externalPort" --glob "**/*.{test,spec}.{ts,tsx,js,jsx}" -A 2

Length of output: 2150


Script:

#!/bin/bash
# Check how externalPort is handled in the implementation
rg "externalPort" e2e/utils.ts -B 2 -A 2

Length of output: 526

index.ts (2)

Line range hint 89-103: Clarify the purpose of port-related CLI options.

The code defines two port-related options (--port and --external-port) but their purposes and differences are not clearly documented. This becomes especially important given the ongoing parameter renaming from externalPort to port.

Let's check the documentation and usage examples:

#!/bin/bash
# Search for documentation about ports
echo "Searching for port-related documentation..."
fd -e md -e txt . -x rg -l "port"

# Search for usage examples
echo "Searching for usage examples..."
fd README.md -x rg -A 5 -B 5 "\-\-port|\-\-external\-port"

Consider improving the CLI option descriptions:

  .option(
    "--port <port>",
-    `\n\n  Select UI port.`,
+    `\n\n  Specify the port number for the UI server (default: 3000).`,
  )
  .option(
    "--external-port <external>",
-    `\n\n  Select external port.`,
+    `\n\n  Specify the port number for external access, useful when running behind a proxy or in a container (default: same as --port).`,
  )

336-336: ⚠️ Potential issue

Inconsistent port parameter usage detected.

The code uses port in createApp but still maintains both port and externalPort in the runApp call. This inconsistency could lead to confusion.

Let's verify the usage of these parameters across the codebase:

helpers/typescript.ts (1)

244-247: Verify impact on frontend-only installations.

The addition of the backend condition aligns with the PR objective of integrating frontend with backend. However, let's verify that this change doesn't break frontend-only installations.

✅ Verification successful

The backend condition is safe and correctly implemented

The verification shows that the change is safe for frontend-only installations because:

  1. The condition only affects TypeScript dependency installation for backend components
  2. Frontend configurations in questions/simple.ts are handled separately and remain unaffected
  3. The postInstallAction logic is consistently applied across the codebase, with similar patterns in helpers/python.ts and helpers/llama-pack.ts
  4. Test files show that frontend and backend installations are properly segregated with the --no-frontend flag
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any frontend-only installation flows that might be affected

# Search for frontend-only installation patterns
rg -A 5 "installTSTemplate.*backend:\s*false"

# Search for test cases involving frontend-only installations
rg -A 10 "describe.*frontend.*installation|test.*frontend.*installation"

Length of output: 122


Script:

#!/bin/bash
# Let's analyze the installTSTemplate function usage and implementation

# Find the implementation of installTSTemplate
ast-grep --pattern 'export async function installTSTemplate($_'

# Find all calls to installTSTemplate
rg -A 3 'installTSTemplate\(' 

# Look for any frontend-related configuration or setup
rg -A 5 'frontend.*=.*true|frontend.*:.*true'

Length of output: 1614


Script:

#!/bin/bash
# Let's examine the full implementation to understand the control flow

# Look at the full implementation of installTSTemplate
rg -B 10 -A 20 'export async function installTSTemplate'

# Check if there are any other conditions or handlers for frontend installations
rg -B 3 -A 3 'postInstallAction.*=|postInstallAction.*:'

Length of output: 8684

questions/questions.ts (1)

126-129: Verify: Express frontend support removal

The condition for frontend generation has been changed to only support FastAPI. Previously, it supported both Express and FastAPI. Please confirm if removing Express frontend support is intentional, as this could be a breaking change for existing users.

helpers/env-variables.ts (2)

556-556: LGTM: Parameter renaming is consistent

The renaming from externalPort to port aligns with the broader changes across the codebase and improves naming clarity.


573-573: Consider improving port handling logic

While the parameter renaming is correct, there's a FIXME comment indicating that NextJS port should be 3000. Consider:

  1. Making the port handling more explicit
  2. Adding validation to prevent port conflicts between frontend and backend

Let's verify the port usage across the codebase:

Consider implementing a port availability check and adding a warning if the specified port conflicts with the default NextJS port (3000).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
helpers/run-app.ts (3)

46-52: Enhance build feedback and error handling

While the implementation is correct, consider adding more descriptive logging to help users track the build progress and diagnose failures more easily.

 export function buildFrontend(appPath: string, framework: TemplateFramework) {
+  console.log(`Building frontend using ${framework === "fastapi" ? "poetry" : "npm"}...`);
   const packageManager = framework === "fastapi" ? "poetry" : "npm";
   return createProcess(packageManager, ["run", "build"], {
     stdio: "inherit",
     cwd: appPath,
   });
 }

92-94: Enhance error reporting

The current error message doesn't provide enough context about what specifically failed (build or run phase).

   } catch (error) {
-    console.error("Failed to run app:", error);
+    const phase = error.message?.includes('build') ? 'build' : 'run';
+    console.error(`Failed to ${phase} app:`, error);
+    console.error('Please check the logs above for more details.');
     throw error;
   }

89-90: Centralize default port configuration

Consider extracting the default port values to a configuration constant to improve maintainability.

+const DEFAULT_PORTS = {
+  nextjs: 3000,
+  fastapi: 8000,
+} as const;
+
 export async function runApp(/*...*/) {
   // ...
-      const defaultPort = framework === "nextjs" ? 3000 : 8000;
+      const defaultPort = DEFAULT_PORTS[framework];
       await appRunner(appPath, port || defaultPort);
   // ...
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 78c7798 and 18e7c0e.

📒 Files selected for processing (1)
  • helpers/run-app.ts (3 hunks)
🔇 Additional comments (1)
helpers/run-app.ts (1)

15-19: Fix Promise resolution logic to prevent multiple settlements

The Promise can still be settled multiple times if the process exits with a non-zero code.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
helpers/run-app.ts (2)

28-34: Enhance error messaging for build failures

The build errors could be more descriptive to help diagnose frontend build issues.

Consider this enhancement:

 export function buildFrontend(appPath: string, framework: TemplateFramework) {
   const packageManager = framework === "fastapi" ? "poetry" : "npm";
+  console.log(`Building frontend using ${packageManager}...`);
   return createProcess(packageManager, ["run", "build"], {
     stdio: "inherit",
     cwd: appPath,
   });
 }

74-94: Improve error handling and type safety

Consider these enhancements:

  1. Use custom error types for different failure scenarios
  2. Make template parameter type-safe using an enum

Example implementation:

enum Template {
  EXTRACTOR = "extractor",
  STREAMING = "streaming",
  MULTIAGENT = "multiagent"
}

class AppRunnerError extends Error {
  constructor(message: string, public readonly cause?: unknown) {
    super(message);
    this.name = 'AppRunnerError';
  }
}

export async function runApp(
  appPath: string,
  template: Template, // Use enum instead of string
  frontend: boolean,
  framework: TemplateFramework,
  port?: number,
): Promise<void> {
  try {
    // ... existing code ...
  } catch (error) {
    throw new AppRunnerError(
      `Failed to run app with template ${template}`,
      error
    );
  }
}
e2e/utils.ts (1)

Line range hint 19-141: Consider updating documentation to reflect port handling changes

The simplification of port handling from dual (port/externalPort) to single (port) configuration is a good architectural improvement. Consider:

  1. Updating any API documentation to reflect these changes
  2. Adding migration notes for users updating from previous versions
  3. Documenting the new port configuration approach in the testing guide

This will help users understand and adapt to the new simplified approach.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 18e7c0e and 8aa26e9.

📒 Files selected for processing (8)
  • e2e/python/resolve_dependencies.spec.ts (0 hunks)
  • e2e/shared/extractor_template.spec.ts (0 hunks)
  • e2e/shared/multiagent_template.spec.ts (3 hunks)
  • e2e/typescript/resolve_dependencies.spec.ts (0 hunks)
  • e2e/utils.ts (1 hunks)
  • helpers/run-app.ts (2 hunks)
  • index.ts (1 hunks)
  • questions/types.ts (1 hunks)
💤 Files with no reviewable changes (3)
  • e2e/python/resolve_dependencies.spec.ts
  • e2e/shared/extractor_template.spec.ts
  • e2e/typescript/resolve_dependencies.spec.ts
🔇 Additional comments (8)
questions/types.ts (1)

5-5: Verify property naming consistency across codebase

The change includes the port-related property in QuestionResults, but there might be an inconsistency. The AI summary indicates that externalPort is being renamed to port across the codebase, but this change simply includes the property without renaming it.

Let's verify the property naming in related files:

✅ Verification successful

Based on the search results, I can now generate the final response:

Property naming is consistent with port across the codebase

The verification shows that:

  • No occurrences of externalPort property were found in interfaces or usage
  • All port-related properties consistently use port naming across the codebase
  • The property is correctly typed as number | null in various interfaces

Therefore, removing "externalPort" from the Omit type is the correct approach as it aligns with the consistent use of port throughout the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the usage of 'externalPort' and 'port' properties in type definitions
# and their usage across the codebase to ensure consistency

# Check type definitions and interfaces
echo "Checking type definitions for port properties..."
ast-grep --pattern 'interface $_ {
  $$$
  port: $_
  $$$
}'

ast-grep --pattern 'interface $_ {
  $$$
  externalPort: $_
  $$$
}'

# Check property usage in code
echo "Checking property usage..."
rg -A 2 'externalPort:' 
rg -A 2 'port:'

Length of output: 5342

helpers/run-app.ts (1)

15-19: ⚠️ Potential issue

Fix Promise resolution logic to prevent multiple settlements

The Promise can be settled twice if the process exits with a non-zero code. Currently, resolve() is called unconditionally after the if block.

Apply this fix:

  if (code !== 0) {
    console.log(`Child process exited with code=${code}`);
    reject(code);
+  } else {
    resolve();
+  }

Likely invalid or redundant comment.

e2e/shared/multiagent_template.spec.ts (3)

73-76: LGTM! Clear and well-documented test skip conditions

The skip conditions are well-defined and properly documented with a clear comment explaining why specific agents are excluded.


61-64: Verify Express framework exclusion rationale

The skip condition for Express framework has been added, but the rationale for excluding Express isn't immediately clear.

#!/bin/bash
# Description: Verify Express framework frontend integration support

# Check for Express frontend integration patterns
echo "Checking Express frontend integration patterns:"
rg -A 5 'express.*frontend|frontend.*express'

# Check for similar Express framework exclusions in other tests
echo "Checking Express framework exclusions in other tests:"
rg -A 2 'skip.*express' e2e/

19-19: Verify frontend integration with FastAPI framework

The change to assign "--frontend" for FastAPI framework needs verification to ensure it aligns with the application's architecture.

✅ Verification successful

Frontend integration pattern is consistent across templates

The appType assignment is correctly implemented and consistent with the codebase patterns:

  • Same frontend integration logic is used in streaming_template.spec.ts
  • The FastAPI-frontend relationship is consistently handled across test files
  • Express framework is properly excluded from frontend tests in both streaming and multiagent templates
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify frontend integration patterns across the codebase

# Check for similar frontend type assignments in other test files
echo "Checking frontend type assignments in other test files:"
rg -l 'appType.*=.*--frontend.*fastapi' e2e/

# Check for frontend integration patterns in FastAPI setup
echo "Checking FastAPI frontend integration patterns:"
rg -A 5 'fastapi.*frontend|frontend.*fastapi'

Length of output: 395


Script:

#!/bin/bash
# Let's try a different approach to verify the frontend integration patterns

# Search for appType assignments in test files
echo "Checking appType assignments in test files:"
rg -A 2 'appType.*=.*template' e2e/

# Search for frontend-related configurations or patterns
echo "Checking frontend-related patterns:"
rg -A 3 '--frontend' .

# Search for framework-specific test configurations
echo "Checking framework-specific test configurations:"
rg -A 3 'templateFramework.*=.*("fastapi"|"express")' e2e/

Length of output: 3818

e2e/utils.ts (2)

141-141: LGTM: Port waiting logic simplified

The simplified port waiting logic is more maintainable and aligns well with the removal of externalPort. This change reduces complexity while maintaining the necessary functionality.


Line range hint 19-39: Verify test updates after port configuration changes

The removal of externalPort from RunCreateLlamaOptions simplifies the API, but this is a breaking change that requires verification of all dependent test files.

✅ Verification successful

Port configuration changes have been properly updated across the codebase

The verification shows that:

  • No references to externalPort remain in any e2e test files
  • All files using RunCreateLlamaOptions have been identified and the changes are consistent
  • The breaking change has been properly propagated across the test suite
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that all test files have been updated to remove externalPort usage

# Search for any remaining references to externalPort in test files
echo "Checking for remaining externalPort references in test files:"
rg -l 'externalPort' 'e2e/**/*.ts' 'e2e/**/*.tsx'

# Search for test files that might need updates based on RunCreateLlamaOptions usage
echo "Checking for potential test files using RunCreateLlamaOptions:"
rg -l 'RunCreateLlamaOptions' 'e2e/**/*.ts' 'e2e/**/*.tsx'

Length of output: 586


Script:

#!/bin/bash
# Let's try without glob patterns since they're not working
# First find all TypeScript files in e2e directory
echo "Finding all TypeScript files:"
fd -e ts -e tsx . e2e/

# Then search for externalPort references
echo -e "\nChecking for remaining externalPort references:"
rg 'externalPort' e2e/

# Search for RunCreateLlamaOptions usage
echo -e "\nChecking for RunCreateLlamaOptions usage:"
rg 'RunCreateLlamaOptions' e2e/

Length of output: 885

index.ts (1)

329-329: LGTM! Port parameter alignment has been addressed.

The changes correctly simplify the port handling by using a single port parameter consistently between createApp and runApp functions, addressing the previous review comment about port parameter alignment.

Let's verify that the --external-port option has been completely removed:

✅ Verification successful

Based on the search results, I can now generate the final response:

Port parameter has been successfully simplified

The search results confirm that:

  • The --external-port option has been completely removed from the codebase
  • Only a single --port option is used consistently throughout
  • Port handling is properly aligned between different components:
    • CLI uses --port option
    • Express apps use process.env.PORT || "8000"
    • FastAPI uses APP_PORT env var defaulting to "8000"
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining references to external port
# Test: Search for "external" or "externalPort". Expect: No occurrences related to port configuration.
rg -i "external.*port|port.*external"

Length of output: 39


Script:

#!/bin/bash
# Let's try a broader search for any port-related configuration or CLI options
rg -i "port.*=|--port" -A 2 -B 2

Length of output: 47527


Script:

#!/bin/bash
# Search for any port-related type definitions or interfaces
ast-grep --pattern 'interface $_ {
  $$$
  port$_: $_
  $$$
}'

Length of output: 64


Script:

#!/bin/bash
# Look for CLI option definitions related to port
rg -i "addOption.*port" -A 2

Length of output: 30

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
templates/types/streaming/fastapi/run.py (3)

51-51: Remove redundant dirs_exist_ok parameter.

Since we're ensuring the static directory is empty before copying (lines 47-49), the dirs_exist_ok=True parameter is unnecessary.

-        shutil.copytree(frontend_dir / "out", static_dir, dirs_exist_ok=True)
+        shutil.copytree(frontend_dir / "out", static_dir)

58-61: Enhance error messages with build step context.

The current error messages could be more specific about which build step failed.

     except CalledProcessError as e:
-        raise SystemError(f"Build failed during {e.cmd}") from e
+        step = "dependency installation" if "install" in e.cmd else "build"
+        raise SystemError(f"Frontend {step} failed: {e.cmd} returned non-zero exit status {e.returncode}") from e
     except Exception as e:
-        raise SystemError(f"Build failed: {str(e)}") from e
+        raise SystemError(f"Frontend build failed during file operations: {str(e)}") from e

64-78: Consider adding timeout and poetry existence check.

While the implementation is solid, consider these improvements:

  1. Add a check for poetry's existence
  2. Add timeout handling for the subprocess
+import sys
+from shutil import which
+
 def dev():
     """
     Start fastapi app using poetry's virtual environment.
 
     Raises:
-        SystemError: If the app fails to start
+        SystemError: If poetry is not found or the app fails to start
     """
+    if which("poetry") is None:
+        raise SystemError(
+            "Poetry is not installed. Please install poetry first: https://python-poetry.org/docs/#installation"
+        )
+
     rich.print("\n[bold]Starting app[/bold]")
     try:
-        run(["poetry", "run", "python", "main.py"], check=True)
+        run(["poetry", "run", "python", "main.py"], check=True, timeout=300)  # 5 min timeout
     except KeyboardInterrupt:
         rich.print("\n[bold yellow]Shutting down...[/bold yellow]")
         return
+    except TimeoutExpired:
+        raise SystemError("App startup timed out after 5 minutes")
     except Exception as e:
         raise SystemError(f"Failed to start app: {str(e)}") from e
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8aa26e9 and 61117be.

📒 Files selected for processing (1)
  • templates/types/streaming/fastapi/run.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🔇 Additional comments (1)
templates/types/streaming/fastapi/run.py (1)

9-24: LGTM! Clean and secure implementation.

The function follows best practices by:

  • Using which for safe package manager detection
  • Including proper type hints and documentation
  • Providing clear error messages

@leehuwuj leehuwuj changed the title Add frontend code and build script to backend Simplify FastAPI fullstack template by include frontend code and a build script Nov 19, 2024
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (7)
templates/types/streaming/fastapi/pyproject.toml (1)

26-26: Consider updating psutil to a newer version

The current version (6.1.0) is quite old. Consider updating to the latest stable version (5.9.8) which includes important fixes and improvements.

-psutil = "^6.1.0"
+psutil = "^5.9.8"
templates/types/streaming/fastapi/run.py (4)

29-29: Add timeouts to prevent hanging on long-running commands

The build commands could potentially hang indefinitely. Consider adding timeouts to prevent this.

-run([package_manager, "install"], cwd=frontend_dir, check=True)
+run([package_manager, "install"], cwd=frontend_dir, check=True, timeout=300)  # 5 minutes

-run([package_manager, "run", "build"], cwd=frontend_dir, check=True)
+run([package_manager, "run", "build"], cwd=frontend_dir, check=True, timeout=300)  # 5 minutes

Also applies to: 32-32


56-57: Track TODO for production mode implementation

The production mode implementation is currently missing. This should be tracked for future implementation.

Would you like me to create a GitHub issue to track the implementation of the production mode?


82-87: Enhance server shutdown logging

Add progress logging during server shutdown to improve observability.

 for process in (frontend_process, backend_process):
+    rich.print(f"\n[bold yellow]Terminating process {process.pid}...[/bold yellow]")
     process.terminate()
     try:
         await asyncio.wait_for(process.wait(), timeout=5)
+        rich.print(f"[bold green]Process {process.pid} terminated gracefully[/bold green]")
     except asyncio.TimeoutError:
+        rich.print(f"[bold red]Force killing process {process.pid}[/bold red]")
         process.kill()

208-209: Improve exception chaining in process lookup

The exception should preserve the original error context.

-            raise ProcessLookupError(f"Process {pid} not found or access denied")
+            raise ProcessLookupError(f"Process {pid} not found or access denied") from None
🧰 Tools
🪛 Ruff

209-209: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

templates/types/streaming/fastapi/app/middlewares/frontend.py (2)

22-52: Consider reusing the httpx.AsyncClient session

Creating a new httpx.AsyncClient instance for each request can be inefficient. Reusing the client session can improve performance by utilizing connection pooling.

Apply this diff to reuse the client session:

+        self.client = httpx.AsyncClient()
+
     async def _request_frontend(self, request: Request, path: str):
-        async with httpx.AsyncClient() as client:
+        client = self.client
             url = urllib.parse.urljoin(f"{self.frontend_endpoint}/", path)
             ...

+    async def __del__(self):
+        await self.client.aclose()

59-61: Ensure support for WebSocket connections

The middleware currently bypasses non-HTTP requests. If the frontend requires WebSocket support, consider handling 'websocket' connection types appropriately.

Consider updating the condition:

         if scope["type"] != "http":
+            if scope["type"] == "websocket":
+                # Optionally handle WebSocket proxying here
+                pass
             return await self.app(scope, receive, send)

If WebSocket support is needed, implement the necessary logic to proxy WebSocket connections.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 26dfec6 and 60f546e.

📒 Files selected for processing (5)
  • templates/types/streaming/fastapi/app/middlewares/frontend.py (1 hunks)
  • templates/types/streaming/fastapi/gitignore (1 hunks)
  • templates/types/streaming/fastapi/main.py (2 hunks)
  • templates/types/streaming/fastapi/pyproject.toml (2 hunks)
  • templates/types/streaming/fastapi/run.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • templates/types/streaming/fastapi/gitignore
  • templates/types/streaming/fastapi/main.py
🧰 Additional context used
📓 Path-based instructions (3)
templates/types/streaming/fastapi/app/middlewares/frontend.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/pyproject.toml (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🪛 Ruff
templates/types/streaming/fastapi/run.py

209-209: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (2)
templates/types/streaming/fastapi/pyproject.toml (2)

22-22: LGTM: Rich library addition

The rich library is a good choice for terminal formatting and the version constraint is appropriate.


10-12: Verify the existence of run module functions

The script entries look good and follow common patterns. However, let's verify that the referenced functions exist in the run module.

✅ Verification successful

Script entries are correctly implemented

The run.py module contains all the required functions referenced in the pyproject.toml scripts:

  • dev(): Starts development servers for both frontend and backend with hot reloading
  • prod(): Currently a placeholder for production mode (raises NotImplementedError)
  • build(): Builds frontend assets and copies them to the static directory

The implementation is well-structured and includes proper error handling, logging, and process management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the run module exists and contains the referenced functions

# Search for the run module and its functions
rg -t python "def (dev|prod|build)" --type python

Length of output: 82


Script:

#!/bin/bash
# Search for Python files that might contain the run module
fd -e py run.py

# Search for any Python file containing these function definitions
rg "def (dev|prod|build)"

Length of output: 245


Script:

#!/bin/bash
# Let's examine the implementation of these functions
cat templates/types/streaming/fastapi/run.py

Length of output: 6882

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (4)
templates/types/streaming/fastapi/run.py (4)

52-54: Track TODO for production mode implementation.

The TODO comment for production mode implementation should be tracked to ensure it's not forgotten.

Would you like me to create a GitHub issue to track the production mode implementation?


57-88: Consider capturing process output for debugging.

While the process management is robust, consider capturing process output for debugging purposes. This would help in troubleshooting when servers fail to start or encounter issues.

 frontend_process, frontend_port = await _run_frontend()
 frontend_endpoint = f"http://localhost:{frontend_port}"
-backend_process = await _run_backend(frontend_endpoint)
+backend_process = await _run_backend(
+    frontend_endpoint,
+    stdout=asyncio.subprocess.PIPE,
+    stderr=asyncio.subprocess.PIPE
+)

120-120: Remove debug print statement.

The print statement for debugging the return code should be removed from production code.

-        print("Return code:", frontend_process.returncode)

204-218: Consider using contextlib for cleaner socket handling.

While the implementation is correct, it could be more elegant using contextlib for socket operations.

+from contextlib import closing
+
 def _is_bindable_port(port: int) -> bool:
     """Check if a port is available by attempting to connect to it."""
-    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
+    with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
         try:
             s.connect(("localhost", port))
             return False
         except ConnectionRefusedError:
             return True
         except socket.error:
             return True
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 60f546e and 1b993b9.

📒 Files selected for processing (2)
  • templates/types/streaming/fastapi/pyproject.toml (2 hunks)
  • templates/types/streaming/fastapi/run.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • templates/types/streaming/fastapi/pyproject.toml
🧰 Additional context used
📓 Path-based instructions (1)
templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🔇 Additional comments (3)
templates/types/streaming/fastapi/run.py (3)

1-13: LGTM! Well-organized imports and constants.

The imports are appropriately organized and the constants are well-defined at the module level.


15-46: LGTM! Robust build implementation.

The build function implementation is secure and reliable with:

  • Proper error handling and cleanup
  • Safe subprocess execution
  • Clear user feedback

151-185: LGTM! Robust package management implementation.

The implementation is secure and thorough with:

  • Windows compatibility
  • Multiple package manager support
  • Proper error handling

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (12)
templates/components/agents/python/financial_report/README-template.md (2)

40-43: Consider adding security recommendations for production.

While the production setup is clearly documented, it would be helpful to include security recommendations regarding CORS configuration in production.

Consider adding a note like:

 The API allows CORS for all origins to simplify development. For **production**, you should run:

```shell
poetry run prod

+> Note: In production, configure CORS to allow only trusted origins by setting the ALLOWED_ORIGINS environment variable.


<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

42-42: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

---

`43-43`: **Add shell language specification to code fence.**

For better documentation and syntax highlighting, specify the language for the code fence.

```diff
-```
+```shell
 poetry run prod

</blockquote></details>
<details>
<summary>templates/components/agents/python/form_filling/README-template.md (2)</summary><blockquote>

`46-49`: **Security consideration for CORS configuration.**

The documentation correctly highlights that allowing CORS for all origins should only be used in development. However, it would be helpful to provide more specific guidance for production settings.

Consider adding a note about configuring CORS for specific origins in production, like:

```diff
 The API allows CORS for all origins to simplify development. For **production**, you should run:

+> **_Important:_** In production, configure CORS to allow only specific trusted origins by setting the `CORS_ORIGINS` environment variable.
+
🧰 Tools
🪛 Markdownlint

48-48: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


48-48: Add language specification to code block.

The code block should specify a language for better syntax highlighting and documentation consistency.

-```
+```shell
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

48-48: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>templates/types/streaming/fastapi/main.py (2)</summary><blockquote>

`29-36`: **Consider adding type hints to improve code clarity.**

The function modification is well-implemented, but could benefit from type hints for better maintainability.

```diff
-def mount_static_files(directory, path, html=False):
+def mount_static_files(directory: str, path: str, html: bool = False):

Line range hint 73-78: Consider adding environment variable validation.

While the environment variable usage is correct, consider adding validation for critical variables like APP_PORT.

-    app_port = int(os.getenv("APP_PORT", "8000"))
+    try:
+        app_port = int(os.getenv("APP_PORT", "8000"))
+        if not (0 < app_port < 65536):
+            raise ValueError("Port must be between 1 and 65535")
+    except ValueError as e:
+        logger.error(f"Invalid APP_PORT: {e}")
+        app_port = 8000
templates/components/agents/python/blog/README-template.md (1)

52-55: Add language specification to the fenced code block.

The command block should specify the language for better syntax highlighting and documentation consistency.

Apply this change:

 The API allows CORS for all origins to simplify development. For **production**, you should run:

-```
+```shell
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

54-54: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>templates/types/streaming/fastapi/README-template.md (3)</summary><blockquote>

`24-31`: **Clarify the browser access instructions**

The current instructions don't specify what users will see when accessing localhost:8000. Consider generalizing it to handle both frontend and backend cases.

Apply this diff to clarify the instructions:

```diff
 Third, run the app:

 ```bash
 poetry run dev

-Open http://localhost:8000 with your browser to start the app.
+Open http://localhost:8000 with your browser to start the app. If you didn't generate a frontend, you will see the Swagger UI of the backend.


<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

---

`55-58`: **Enhance production deployment security guidance**

While the CORS warning is helpful, consider adding more production security considerations.

Add security recommendations like:
```diff
 The API allows CORS for all origins to simplify development. For **production**, you should:
+- Configure specific allowed origins in the CORS settings
+- Enable HTTPS
+- Set appropriate rate limiting
+- Review and adjust logging levels
 
 ```bash
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

57-57: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

---

`26-26`: **Add language specifiers to code blocks**

Add language specifiers to the code blocks for better syntax highlighting.

Apply these changes:
1. Add 'bash' to the code block at line 26
2. Add 'bash' to the code block at line 57


Also applies to: 57-57

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>templates/types/streaming/fastapi/run.py (2)</summary><blockquote>

`21-52`: **Consider enhancing error messages with more context.**

The build function is well-structured with proper error handling. However, the error messages could be more descriptive.

Consider this enhancement:

```diff
-        raise SystemError(f"Build failed during {e.cmd}") from e
+        raise SystemError(f"Build failed during '{' '.join(e.cmd)}'. Exit code: {e.returncode}") from e

263-270: Consider adding a maximum retry count for port finding.

The current implementation might try too many ports before giving up. Consider limiting the range to a reasonable number of attempts.

Consider this enhancement:

-def _find_free_port(start_port: int) -> int:
+def _find_free_port(start_port: int, max_attempts: int = 100) -> int:
     """
     Find a free port starting from the given port number.
+
+    Args:
+        start_port: The port number to start searching from
+        max_attempts: Maximum number of ports to try
+
+    Raises:
+        SystemError: If no free port is found within max_attempts
     """
-    for port in range(start_port, 65535):
+    for port in range(start_port, min(start_port + max_attempts, 65535)):
         if _is_bindable_port(port):
             return port
-    raise SystemError("No free port found")
+    raise SystemError(f"No free port found after trying {max_attempts} ports starting from {start_port}")
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1b993b9 and e2e53e2.

📒 Files selected for processing (8)
  • templates/components/agents/python/blog/README-template.md (2 hunks)
  • templates/components/agents/python/financial_report/README-template.md (2 hunks)
  • templates/components/agents/python/form_filling/README-template.md (2 hunks)
  • templates/types/streaming/fastapi/README-template.md (2 hunks)
  • templates/types/streaming/fastapi/app/config.py (1 hunks)
  • templates/types/streaming/fastapi/app/middlewares/frontend.py (1 hunks)
  • templates/types/streaming/fastapi/main.py (3 hunks)
  • templates/types/streaming/fastapi/run.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • templates/types/streaming/fastapi/app/config.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • templates/types/streaming/fastapi/app/middlewares/frontend.py
🧰 Additional context used
📓 Path-based instructions (6)
templates/components/agents/python/blog/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/components/agents/python/financial_report/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/components/agents/python/form_filling/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/main.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🪛 Markdownlint
templates/components/agents/python/blog/README-template.md

54-54: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/components/agents/python/financial_report/README-template.md

42-42: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/components/agents/python/form_filling/README-template.md

48-48: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/types/streaming/fastapi/README-template.md

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


57-57: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff
templates/types/streaming/fastapi/run.py

171-171: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🔇 Additional comments (9)
templates/components/agents/python/financial_report/README-template.md (1)

24-24: LGTM! Clear and simplified development command.

The new poetry run dev command follows modern Python project conventions and improves user experience.

templates/types/streaming/fastapi/main.py (5)

2-2: LGTM! Import structure follows best practices.

The import order is correct, with environment variables being loaded before other imports, and the new imports are properly organized.

Also applies to: 12-12


39-44: LGTM! Proper route and static file mounting setup.

The order of mounting (API routes followed by static files) is correct and the paths are well-structured to avoid conflicts.


46-56: LGTM! Good environment-specific configuration with proper logging.

The conditional setup for development environment is well-structured with appropriate fallback behavior and warning logs.


69-71: LGTM! Proper production setup with static file serving.

The production environment configuration is secure and well-implemented.


49-53: Verify the excluded paths implementation.

Let's ensure that the excluded_paths set comprehension correctly captures all API routes to prevent proxy conflicts.

✅ Verification successful

Let me check the route definitions in main.py to ensure we have a complete picture.


Let me check the API router to see all the routes that should be excluded.


Let me try to find the API router file using fd.


Based on the code analysis, I can now provide the final response:

The excluded paths implementation is correctly implemented and secure.

The implementation is verified to be correct because:

  1. The middleware correctly collects all routes via set(route.path for route in app.router.routes), which includes:
    • All API routes from the included router (app.include_router(api_router, prefix="/api"))
    • The static file mounts for /api/files/data and /api/files/output
    • The docs redirect route in dev mode
  2. The _is_excluded_path method in FrontendProxyMiddleware properly checks if incoming paths start with any excluded path
  3. The middleware is only active in dev mode with proper environment checks
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of FrontendProxyMiddleware and its excluded paths

# Check the middleware implementation
ast-grep --pattern 'class FrontendProxyMiddleware:
  $$$
  async def __call__($$$):
    $$$'

# Look for any route definitions that might be missed
rg -l 'app\.(?:get|post|put|delete|patch)\s*\(' --type py

Length of output: 6402


Script:

#!/bin/bash
# Check the route definitions in main.py
cat templates/types/streaming/fastapi/main.py

Length of output: 2411


Script:

#!/bin/bash
# Check the API router implementation
cat templates/types/streaming/fastapi/app/api/routers.py

Length of output: 143


Script:

#!/bin/bash
# Find and examine the router implementation
fd -t f routers.py
fd -t f router.py

Length of output: 40

templates/components/agents/python/blog/README-template.md (1)

35-35: LGTM! Command simplification improves user experience.

The simplified command poetry run dev is more intuitive and follows common development practices.

templates/types/streaming/fastapi/run.py (2)

1-19: LGTM! Well-structured imports and constants.

The imports are properly organized, and constants are defined with appropriate environment variable fallbacks.


62-128: LGTM! Robust server management implementation.

The server management functions handle process lifecycle, error cases, and graceful shutdown effectively. The timeout-based termination is a good practice.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
templates/types/streaming/fastapi/app/middlewares/frontend.py (3)

11-25: LGTM with a minor documentation enhancement

The class initialization is well-structured with proper type hints. Consider enhancing the docstring to include parameter descriptions.

Add parameter descriptions to the docstring:

     """
     Proxy requests to the frontend development server
+    
+    Args:
+        app: The ASGI application instance
+        frontend_endpoint: The URL of the frontend development server
+        excluded_paths: Set of path prefixes to exclude from proxying
     """

41-48: Consider adding request cancellation handling

The proxy request should be cancelled if the client disconnects to prevent unnecessary processing.

+                # Create a task for the proxy request
+                request_task = asyncio.create_task(
+                    client.request(
+                        method=request.method,
+                        url=url,
+                        headers=headers,
+                        content=body,
+                        follow_redirects=True,
+                    )
+                )
+                
+                # Handle client disconnection
+                disconnect = asyncio.create_task(receive())
+                done, pending = await asyncio.wait(
+                    [request_task, disconnect],
+                    return_when=asyncio.FIRST_COMPLETED
+                )
+                
+                if disconnect in done:
+                    request_task.cancel()
+                    return None
+                
+                response = await request_task

62-66: Consider optimizing path exclusion checks and adding path normalization

The current implementation checks each excluded path sequentially. For better security and performance:

  1. Normalize paths before comparison
  2. Consider using a trie structure for large sets of excluded paths
     def _is_excluded_path(self, path: str) -> bool:
+        # Normalize path for consistent comparison
+        normalized_path = posixpath.normpath(path).lstrip('/')
         return any(
-            path.startswith(excluded_path) for excluded_path in self.excluded_paths
+            normalized_path.startswith(excluded_path) for excluded_path in self.excluded_paths
         )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e2e53e2 and 6c8497e.

📒 Files selected for processing (1)
  • templates/types/streaming/fastapi/app/middlewares/frontend.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
templates/types/streaming/fastapi/app/middlewares/frontend.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🔇 Additional comments (2)
templates/types/streaming/fastapi/app/middlewares/frontend.py (2)

1-8: LGTM: Imports and logging setup are appropriate

The imports are well-organized and the logging configuration is correctly set up using uvicorn's logger.


26-31: LGTM: Request handling method signature is well-defined

The timeout parameter with a reasonable default value is a good addition for controlling request timeouts.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (9)
templates/components/agents/python/financial_report/README-template.md (1)

42-44: Add language specification to code block

For consistency and proper syntax highlighting, specify the language for the code block.

-```
+```shell
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

42-42: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>helpers/run-app.ts (1)</summary><blockquote>

`64-79`: **Improve error handling and maintainability**

While the error handling is good, there are several improvements that could be made:
1. Validate input parameters
2. Make the runner selection more maintainable
3. Add more descriptive error messages

Consider this improved implementation:

```diff
 export async function runApp(
   appPath: string,
   template: string,
   frontend: boolean,
   framework: TemplateFramework,
   port?: number,
 ): Promise<void> {
+  // Validate input parameters
+  if (!appPath) throw new Error('appPath is required');
+  if (!template) throw new Error('template is required');
+  if (!framework) throw new Error('framework is required');
+
+  // Define runner mapping
+  const runners = {
+    extractor: runReflexApp,
+    default: {
+      fastapi: runFastAPIApp,
+      nextjs: runTSApp,
+    },
+  };
+
   try {
     // Start the app
     const defaultPort = framework === "nextjs" ? 3000 : 8000;
-    const appRunner =
-      template === "extractor"
-        ? runReflexApp
-        : framework === "fastapi"
-          ? runFastAPIApp
-          : runTSApp;
+    const appRunner = template === "extractor"
+      ? runners.extractor
+      : runners.default[framework] || runners.default.fastapi;
+
+    console.log(`Starting ${template} app with ${framework} framework...`);
     await appRunner(appPath, port || defaultPort);
   } catch (error) {
-    console.error("Failed to run app:", error);
+    console.error(`Failed to run ${template} app with ${framework} framework:`, error);
     throw error;
   }
 }
templates/components/agents/python/form_filling/README-template.md (1)

46-49: Add shell language specification to the code block.

The production section is a good addition. However, the code block should specify the language for better syntax highlighting.

Apply this change:

 To start the app in **production**, run:
 
-```
+```shell
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

48-48: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>templates/components/agents/python/blog/README-template.md (1)</summary><blockquote>

`54-55`: **Add shell language specification to the code block.**

For better documentation and syntax highlighting, specify the language for the code block.

```diff
-```
+```shell
 poetry run prod

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Markdownlint</summary>

54-54: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>templates/types/streaming/fastapi/README-template.md (2)</summary><blockquote>

`30-31`: **Consider generalizing the browser instruction and adding language to code blocks.**

1. The browser instruction could be more informative by mentioning both frontend and Swagger UI cases.
2. Code blocks should specify the language for better syntax highlighting.

Apply these changes:

```diff
-Open [http://localhost:8000](http://localhost:8000) with your browser to start the app.
+Open [http://localhost:8000](http://localhost:8000) with your browser to start the app. If you didn't generate a frontend, then you will reach the Swagger UI of the backend.

And add language specifications to the code blocks:

-```
+```bash
poetry run dev

55-59: Add language specification to the code block.

The production command looks good, but the code block should specify the language for better documentation.

Add language specification to the code block:

-```
+```bash
poetry run prod
🧰 Tools
🪛 Markdownlint

57-57: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/types/streaming/fastapi/run.py (3)

21-52: Use the STATIC_DIR constant for consistency.

The function creates a local static_dir variable instead of using the STATIC_DIR constant defined at the module level.

-    static_dir = Path("static")
+    static_dir = STATIC_DIR

     try:
         package_manager = _get_node_package_manager()

62-106: Consider adding a timeout constant.

The implementation is robust, but the timeout value (5 seconds) should be defined as a constant at the module level for consistency and maintainability.

+PROCESS_TERMINATION_TIMEOUT = 5  # seconds

 async def start_development_servers():
     # ... existing code ...
     try:
-        await asyncio.wait_for(process.wait(), timeout=5)
+        await asyncio.wait_for(process.wait(), timeout=PROCESS_TERMINATION_TIMEOUT)

130-168: Enhance error messages for better debugging.

The error messages could be more descriptive to help with troubleshooting.

     if frontend_process.returncode is not None:
-        raise RuntimeError("Could not start frontend dev server")
+        raise RuntimeError(
+            f"Frontend dev server failed to start (exit code: {frontend_process.returncode}). "
+            "Check the package.json for correct dev script configuration."
+        )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e72b9cc and ed0f2b6.

📒 Files selected for processing (8)
  • helpers/devcontainer.ts (1 hunks)
  • helpers/run-app.ts (2 hunks)
  • templates/components/agents/python/blog/README-template.md (2 hunks)
  • templates/components/agents/python/financial_report/README-template.md (2 hunks)
  • templates/components/agents/python/form_filling/README-template.md (2 hunks)
  • templates/types/streaming/fastapi/README-template.md (2 hunks)
  • templates/types/streaming/fastapi/main.py (3 hunks)
  • templates/types/streaming/fastapi/run.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • helpers/devcontainer.ts
  • templates/types/streaming/fastapi/main.py
🧰 Additional context used
📓 Path-based instructions (5)
templates/components/agents/python/blog/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/components/agents/python/financial_report/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/components/agents/python/form_filling/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/README-template.md (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

templates/types/streaming/fastapi/run.py (1)

Pattern templates/**: For files under the templates folder, do not report 'Missing Dependencies Detected' errors.

🪛 Markdownlint
templates/components/agents/python/blog/README-template.md

54-54: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/components/agents/python/financial_report/README-template.md

42-42: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/components/agents/python/form_filling/README-template.md

48-48: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/types/streaming/fastapi/README-template.md

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


57-57: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 Ruff
templates/types/streaming/fastapi/run.py

171-171: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🔇 Additional comments (13)
templates/components/agents/python/financial_report/README-template.md (3)

24-24: LGTM: Command update aligns with project standards

The simplified development command follows the new command structure implemented across the project.


38-38: Previous review suggestion implemented correctly


43-43: Verify production command implementation

The simplified production command follows the new structure, but let's verify its implementation.

✅ Verification successful

Let me gather more information about the implementation of the prod command.


Production command is properly implemented

The poetry run prod command is correctly defined in pyproject.toml and implemented in run.py. The implementation:

  • Builds frontend assets if needed
  • Starts the backend server in production mode
  • Handles proper process management and cleanup
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and implementation of the 'prod' command
# Look for pyproject.toml or similar files that might define these commands
fd -t f "pyproject.toml|poetry.toml" --exec cat {} \;

Length of output: 2194


Script:

#!/bin/bash
# Search for the run.py or similar files that might contain the prod implementation
fd -t f "run.py" --exec cat {} \;

# Also search for any file containing the prod function definition
ast-grep --pattern 'def prod():
  $$$'

Length of output: 8716

helpers/run-app.ts (3)

10-12: ⚠️ Potential issue

Security risk: Remove shell: true from spawn options

Using shell: true can introduce security vulnerabilities, especially if any part of the command or args comes from user input. It also adds unnecessary performance overhead.

Apply this diff to remove the security risk:

    spawn(command, args, {
      ...options,
-     shell: true,
    })

29-36: 🛠️ Refactor suggestion

Add port validation and improve logging

The function should validate the port number and provide clear logging about the startup process.

Apply this diff to improve the implementation:

 export function runReflexApp(appPath: string, port: number) {
+  if (port < 1 || port > 65535) {
+    throw new Error(`Invalid port number: ${port}. Port must be between 1 and 65535.`);
+  }
+  console.log(`Starting Reflex app on port ${port}`);
   const commandArgs = [
     "run",
     "reflex",

43-48: 🛠️ Refactor suggestion

Add port validation and improve logging

The function should validate the port number and provide clear logging about the startup process.

Apply this diff to improve the implementation:

 export function runFastAPIApp(appPath: string, port: number) {
+  if (port < 1 || port > 65535) {
+    throw new Error(`Invalid port number: ${port}. Port must be between 1 and 65535.`);
+  }
+  console.log(`Starting FastAPI app on port ${port}`);
   return createProcess("poetry", ["run", "dev"], {
     stdio: "inherit",
     cwd: appPath,
templates/components/agents/python/form_filling/README-template.md (2)

19-19: Skipping comment as it would duplicate existing review.


44-44: LGTM! Clear browser instructions added.

The added instruction provides clear guidance for accessing the application.

templates/components/agents/python/blog/README-template.md (1)

35-35: LGTM! Command simplification improves user experience.

The simplified command poetry run dev makes it easier for users to start the development server.

templates/types/streaming/fastapi/README-template.md (1)

24-27: LGTM! Command change aligns with project standards.

The change to use poetry run dev is consistent with the standardization effort across READMEs.

🧰 Tools
🪛 Markdownlint

26-26: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

templates/types/streaming/fastapi/run.py (3)

1-19: LGTM! Well-structured imports and constants.

The code demonstrates good practices:

  • Proper organization of imports
  • Use of Path objects for directory handling
  • Environment variables with sensible defaults

54-60: LGTM! Clean wrapper functions.

The functions provide a clean synchronous interface to the async implementation.


194-275: LGTM! Well-implemented utility functions.

The utility functions demonstrate good practices:

  • Clear and concise implementations
  • Proper Windows compatibility
  • Comprehensive error handling
  • Informative docstrings

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
helpers/run-app.ts (1)

67-68: Document the default port logic

The default port selection logic could benefit from a comment explaining why specific ports are chosen for different frameworks.

Apply this diff to add documentation:

     const defaultPort =
+      // Use port 3000 for Next.js (standard Next.js port) and Reflex extractor template
+      // Use port 8000 for all other frameworks (standard FastAPI port)
       framework === "nextjs" || template === "extractor" ? 3000 : 8000;
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ed0f2b6 and d3e0fb0.

📒 Files selected for processing (2)
  • helpers/run-app.ts (2 hunks)
  • index.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • index.ts
🔇 Additional comments (3)
helpers/run-app.ts (3)

10-12: ⚠️ Potential issue

Security risk: Remove shell: true from spawn options

Using shell: true can introduce security vulnerabilities, especially if any part of the command or args comes from user input. It also adds unnecessary performance overhead.

Apply this diff to fix the issue:

    spawn(command, args, {
      ...options,
-     shell: true,
    })

29-36: ⚠️ Potential issue

Add port validation and clarify backend port behavior

The function needs validation for the port number and should clarify the backend port behavior since Reflex typically requires both frontend and backend ports.

Apply this diff to add validation and improve clarity:

 export function runReflexApp(appPath: string, port: number) {
+  if (port < 1 || port > 65534) { // Ensure space for backend port
+    throw new Error(`Invalid port number: ${port}. Port must be between 1 and 65534.`);
+  }
+  // Backend port is automatically set to port+1 by Reflex
+  console.log(`Starting Reflex app with frontend port ${port} (backend will use ${port + 1})`);
   const commandArgs = [
     "run",
     "reflex",

59-64: Verify the removal of the frontend parameter

The frontend parameter has been removed from the function signature. Please verify that this doesn't break any existing functionality where the frontend parameter was used to determine behavior.

✅ Verification successful

Removal of frontend parameter is safe and intentional

Based on the git history, the removal of the frontend parameter was part of a cleanup where the frontend-specific logic was also removed. The previous code used this parameter to conditionally build the frontend for "streaming" or "multiagent" templates, but this logic has been completely removed from the function. There are no remaining references to this parameter in the current implementation, indicating this was an intentional change that properly removed all related functionality.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the frontend parameter in the codebase
rg -l "frontend.*parameter|frontend.*arg" --type ts

# Search for calls to runApp with more than 4 arguments
ast-grep --pattern 'runApp($$$, $_, $_, $_, $_, $_)'

Length of output: 108


Script:

#!/bin/bash
# Search for all calls to runApp function to see its usage patterns
ast-grep --pattern 'runApp($_)'

# Search for the history of runApp function definition
rg -A 5 "export.*function runApp" --type ts

# Search for any references to 'frontend' near runApp
rg -B 2 -A 2 "runApp.*frontend|frontend.*runApp" --type ts

Length of output: 391


Script:

#!/bin/bash
# Look for git history of the file to see the previous version
git log -p helpers/run-app.ts | grep -A 15 "function runApp"

# Search for any test files that might be using runApp
fd "test|spec" -e ts -x rg "runApp" {}

# Search for any direct imports and usage of runApp
rg "import.*runApp|from.*run-app" -A 3 --type ts

Length of output: 6398

@marcusschiesser marcusschiesser merged commit fc5b266 into main Nov 20, 2024
46 checks passed
@marcusschiesser marcusschiesser deleted the lee/fullstack branch November 20, 2024 05:38
@keesvanbemmel
Copy link

Is there a reason the pro option to generate a nextjs frontend when choosing express framework backend has been removed?

@marcusschiesser
Copy link
Collaborator

yes, it simplifies the code generator, you can still generate one nextjs frontend and one express backend separately

@keesvanbemmel
Copy link

yes, it simplifies the code generator, you can still generate one nextjs frontend and one express backend separately

thanks for the info!

What's the best way to create those seperately? Can't seem to find those options

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants