reflex/pynecone/utils/build.py
2023-03-16 14:59:27 -07:00

148 lines
4.0 KiB
Python

"""Building the app and initializing all prerequisites."""
from __future__ import annotations
import json
import os
import random
import subprocess
from pathlib import Path
from typing import (
TYPE_CHECKING,
Optional,
)
from pynecone import constants
from pynecone.config import get_config
from pynecone.utils import path_ops, prerequisites
if TYPE_CHECKING:
from pynecone.app import App
def set_pynecone_project_hash():
"""Write the hash of the Pynecone project to a PCVERSION_APP_FILE."""
with open(constants.PCVERSION_APP_FILE) as f: # type: ignore
pynecone_json = json.load(f)
pynecone_json["project_hash"] = random.getrandbits(128)
with open(constants.PCVERSION_APP_FILE, "w") as f:
json.dump(pynecone_json, f, ensure_ascii=False)
def generate_sitemap(deploy_url: str):
"""Generate the sitemap config file.
Args:
deploy_url: The URL of the deployed app.
"""
# Import here to avoid circular imports.
from pynecone.compiler import templates
config = json.dumps(
{
"siteUrl": deploy_url,
"generateRobotsTxt": True,
}
)
with open(constants.SITEMAP_CONFIG_FILE, "w") as f:
f.write(templates.SITEMAP_CONFIG(config=config))
def export_app(
app: App,
backend: bool = True,
frontend: bool = True,
zip: bool = False,
deploy_url: Optional[str] = None,
):
"""Zip up the app for deployment.
Args:
app: The app.
backend: Whether to zip up the backend app.
frontend: Whether to zip up the frontend app.
zip: Whether to zip the app.
deploy_url: The URL of the deployed app.
"""
# Force compile the app.
app.compile(force_compile=True)
# Remove the static folder.
path_ops.rm(constants.WEB_STATIC_DIR)
# Generate the sitemap file.
if deploy_url is not None:
generate_sitemap(deploy_url)
# Export the Next app.
subprocess.run(
[prerequisites.get_package_manager(), "run", "export"], cwd=constants.WEB_DIR
)
# Zip up the app.
if zip:
if os.name == "posix":
posix_export(backend, frontend)
if os.name == "nt":
nt_export(backend, frontend)
def nt_export(backend: bool = True, frontend: bool = True):
"""Export for nt (Windows) systems.
Args:
backend: Whether to zip up the backend app.
frontend: Whether to zip up the frontend app.
"""
cmd = r""
if frontend:
cmd = r'''powershell -Command "Set-Location .web/_static; Compress-Archive -Path .\* -DestinationPath ..\..\frontend.zip -Force"'''
os.system(cmd)
if backend:
cmd = r'''powershell -Command "Get-ChildItem -File | Where-Object { $_.Name -notin @('.web', 'assets', 'frontend.zip', 'backend.zip') } | Compress-Archive -DestinationPath backend.zip -Update"'''
os.system(cmd)
def posix_export(backend: bool = True, frontend: bool = True):
"""Export for posix (Linux, OSX) systems.
Args:
backend: Whether to zip up the backend app.
frontend: Whether to zip up the frontend app.
"""
cmd = r""
if frontend:
cmd = r"cd .web/_static && zip -r ../../frontend.zip ./*"
os.system(cmd)
if backend:
cmd = r"zip -r backend.zip ./* -x .web/\* ./assets\* ./frontend.zip\* ./backend.zip\*"
os.system(cmd)
def setup_frontend(root: Path):
"""Set up the frontend.
Args:
root: root path of the project.
"""
# copy asset files to public folder
path_ops.mkdir(str(root / constants.WEB_ASSETS_DIR))
path_ops.cp(
src=str(root / constants.APP_ASSETS_DIR),
dest=str(root / constants.WEB_ASSETS_DIR),
)
def setup_backend():
"""Set up backend.
Specifically ensures backend database is updated when running --no-frontend.
"""
# Import here to avoid circular imports.
from pynecone.model import Model
config = get_config()
if config.db_url is not None:
Model.create_all()