diff --git a/README.md b/README.md index 787c2d6a9..b390181bb 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ We are actively looking for contributors, no matter your skill level or experien ## More Information More information about Pynecone can be found on our website: -- [Pynecone.io](https://pynecone.io) +- [pynecone.io](https://pynecone.io) ## License diff --git a/pynecone/components/layout/html.py b/pynecone/components/layout/html.py index baeb1570c..3f73ab6bf 100644 --- a/pynecone/components/layout/html.py +++ b/pynecone/components/layout/html.py @@ -1,8 +1,9 @@ """A html component.""" +from typing import Dict + from pynecone.components.layout.box import Box from pynecone.var import Var -from typing import Dict class Html(Box): @@ -33,7 +34,6 @@ class Html(Box): if len(children) != 1: raise ValueError("Must provide children to the html component.") else: - props["dangerouslySetInnerHTML"] = {"__html": children[0]} # Create the component. diff --git a/pynecone/constants.py b/pynecone/constants.py index e7f700568..9269b4ba6 100644 --- a/pynecone/constants.py +++ b/pynecone/constants.py @@ -38,6 +38,8 @@ UTILS_DIR = "utils" STATE_PATH = os.path.join(UTILS_DIR, "state") # The directory where the app pages are compiled to. WEB_PAGES_DIR = os.path.join(WEB_DIR, "pages") +# The directory where the static build is located. +WEB_STATIC_DIR = os.path.join(WEB_DIR, "_static") # The directory where the utils file is located. WEB_UTILS_DIR = os.path.join(WEB_DIR, UTILS_DIR) # The directory where the assets are located. diff --git a/pynecone/pc.py b/pynecone/pc.py index 510727236..7e394ef83 100644 --- a/pynecone/pc.py +++ b/pynecone/pc.py @@ -70,9 +70,11 @@ def run( ) raise typer.Exit() + # Get the app module. utils.console.rule("[bold]Starting Pynecone App") app = utils.get_app() + # Get the frontend and backend commands, based on the environment. frontend_cmd = backend_cmd = None if env == constants.Env.DEV: frontend_cmd, backend_cmd = utils.run_frontend, utils.run_backend @@ -80,10 +82,11 @@ def run( frontend_cmd, backend_cmd = utils.run_frontend_prod, utils.run_backend_prod assert frontend_cmd and backend_cmd, "Invalid env" + # Run the frontend and backend. if frontend: - frontend_cmd(app) + frontend_cmd(app.app) if backend: - backend_cmd(app) + backend_cmd(app.__name__) @cli.command() @@ -104,8 +107,8 @@ def deploy(dry_run: bool = False): # Compile the app in production mode. typer.echo("Compiling production app") - app = utils.get_app() - utils.export_app(app) + app = utils.get_app().app + utils.export_app(app, zip=True) # Exit early if this is a dry run. if dry_run: diff --git a/pynecone/utils.py b/pynecone/utils.py index 702e80283..ee0cc28ef 100644 --- a/pynecone/utils.py +++ b/pynecone/utils.py @@ -15,6 +15,7 @@ import subprocess import sys from collections import defaultdict from subprocess import PIPE +from types import ModuleType from typing import _GenericAlias # type: ignore from typing import ( TYPE_CHECKING, @@ -37,6 +38,7 @@ from pynecone import constants from pynecone.base import Base if TYPE_CHECKING: + from pynecone.app import App from pynecone.components.component import ImportDict from pynecone.config import Config from pynecone.event import Event, EventHandler, EventSpec @@ -308,8 +310,8 @@ def get_bun_path() -> str: return os.path.expandvars(get_config().bun_path) -def get_app() -> Any: - """Get the app based on the default config. +def get_app() -> ModuleType: + """Get the app module based on the default config. Returns: The app based on the default config. @@ -372,11 +374,11 @@ def install_bun(): def install_frontend_packages(): """Install the frontend packages.""" # Install the base packages. - subprocess.call([get_bun_path(), "install"], cwd=constants.WEB_DIR, stdout=PIPE) + subprocess.run([get_bun_path(), "install"], cwd=constants.WEB_DIR, stdout=PIPE) # Install the app packages. packages = get_config().frontend_packages - subprocess.call( + subprocess.run( [get_bun_path(), "add", *packages], cwd=constants.WEB_DIR, stdout=PIPE ) @@ -390,23 +392,30 @@ def is_initialized() -> bool: return os.path.exists(constants.CONFIG_FILE) and os.path.exists(constants.WEB_DIR) -def export_app(app): +def export_app(app: App, zip: bool = False): """Zip up the app for deployment. Args: app: The app. + zip: Whether to zip the app. """ - app.app.compile(force_compile=True) - cmd = r"rm -rf .web/_static; cd .web && bun run export && cd _static && zip -r ../../frontend.zip ./* && cd ../.. && zip -r backend.zip ./* -x .web/\* ./assets\* ./frontend.zip\* ./backend.zip\*" - os.system(cmd) + # Force compile the app. + app.compile(force_compile=True) + + # Remove the static folder. + rm(constants.WEB_STATIC_DIR) + + # Export the Next app. + subprocess.run([get_bun_path(), "run", "export"], cwd=constants.WEB_DIR) + + # Zip up the app. + if zip: + cmd = r"cd .web/_static && zip -r ../../frontend.zip ./* && cd ../.. && zip -r backend.zip ./* -x .web/\* ./assets\* ./frontend.zip\* ./backend.zip\*" + os.system(cmd) -def setup_frontend(app): - """Set up the frontend. - - Args: - app: The app. - """ +def setup_frontend(): + """Set up the frontend.""" # Initialize the web directory if it doesn't exist. cp(constants.WEB_TEMPLATE_DIR, constants.WEB_DIR, overwrite=False) @@ -417,42 +426,38 @@ def setup_frontend(app): # Link the assets folder. ln(src=os.path.join("..", constants.APP_ASSETS_DIR), dest=constants.WEB_ASSETS_DIR) + +def run_frontend(app: App): + """Run the frontend. + + Args: + app: The app. + """ + # Set up the frontend. + setup_frontend() + # Compile the frontend. - app.app.compile(force_compile=True) + app.compile(force_compile=True) - -def run_frontend(app) -> subprocess.Popen: - """Run the frontend. - - Args: - app: The app. - - Returns: - The frontend process. - """ - setup_frontend(app) - command = [get_bun_path(), "run", "dev"] + # Run the frontend in development mode. console.rule("[bold green]App Running") - return subprocess.Popen( - command, cwd=constants.WEB_DIR - ) # stdout=PIPE to hide output + subprocess.Popen([get_bun_path(), "run", "dev"], cwd=constants.WEB_DIR) -def run_frontend_prod(app) -> subprocess.Popen: +def run_frontend_prod(app: App): """Run the frontend. Args: app: The app. - - Returns: - The frontend process. """ - setup_frontend(app) - # Export and zip up the frontend and backend then start the frontend in production mode. - cmd = r"rm -rf .web/_static || true; cd .web && bun run export" - os.system(cmd) - command = [get_bun_path(), "run", "prod"] - return subprocess.Popen(command, cwd=constants.WEB_DIR) + # Set up the frontend. + setup_frontend() + + # Export the app. + export_app(app) + + # Run the frontend in production mode. + subprocess.Popen([get_bun_path(), "run", "prod"], cwd=constants.WEB_DIR) def get_num_workers() -> int: @@ -469,23 +474,23 @@ def get_num_workers() -> int: return (os.cpu_count() or 1) * 2 + 1 -def run_backend(app): +def run_backend(app_name: str): """Run the backend. Args: - app: The app. + app_name: The app name. """ command = constants.RUN_BACKEND + [ - f"{app.__name__}:{constants.APP_VAR}.{constants.API_VAR}" + f"{app_name}:{constants.APP_VAR}.{constants.API_VAR}" ] - subprocess.call(command) + subprocess.run(command) -def run_backend_prod(app) -> None: +def run_backend_prod(app_name: str): """Run the backend. Args: - app: The app. + app_name: The app name. """ num_workers = get_num_workers() command = constants.RUN_BACKEND_PROD + [ @@ -493,9 +498,9 @@ def run_backend_prod(app) -> None: str(num_workers), "--threads", str(num_workers), - f"{app.__name__}:{constants.APP_VAR}()", + f"{app_name}:{constants.APP_VAR}()", ] - subprocess.call(command) + subprocess.run(command) def get_production_backend_url() -> str: