constants.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. """Constants used throughout the package."""
  2. import os
  3. import re
  4. from enum import Enum
  5. from types import SimpleNamespace
  6. import pkg_resources
  7. # App names and versions.
  8. # The name of the Pynecone package.
  9. MODULE_NAME = "pynecone"
  10. # The current version of Pynecone.
  11. VERSION = pkg_resources.get_distribution(MODULE_NAME).version
  12. # Minimum version of Node.js required to run Pynecone.
  13. MIN_NODE_VERSION = "16.8.0"
  14. # Valid bun versions.
  15. MIN_BUN_VERSION = "0.5.9"
  16. MAX_BUN_VERSION = "0.6.1"
  17. # Files and directories used to init a new project.
  18. # The root directory of the pynecone library.
  19. ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  20. # The name of the assets directory.
  21. APP_ASSETS_DIR = "assets"
  22. # The template directory used during pc init.
  23. TEMPLATE_DIR = os.path.join(ROOT_DIR, MODULE_NAME, ".templates")
  24. # The web subdirectory of the template directory.
  25. WEB_TEMPLATE_DIR = os.path.join(TEMPLATE_DIR, "web")
  26. # The assets subdirectory of the template directory.
  27. ASSETS_TEMPLATE_DIR = os.path.join(TEMPLATE_DIR, APP_ASSETS_DIR)
  28. # The jinja template directory.
  29. JINJA_TEMPLATE_DIR = os.path.join(TEMPLATE_DIR, "jinja")
  30. # The frontend directories in a project.
  31. # The web folder where the NextJS app is compiled to.
  32. WEB_DIR = ".web"
  33. # The name of the utils file.
  34. UTILS_DIR = "utils"
  35. # The name of the state file.
  36. STATE_PATH = "/".join([UTILS_DIR, "state"])
  37. # The name of the components file.
  38. COMPONENTS_PATH = "/".join([UTILS_DIR, "components"])
  39. # The directory where the app pages are compiled to.
  40. WEB_PAGES_DIR = os.path.join(WEB_DIR, "pages")
  41. # The directory where the static build is located.
  42. WEB_STATIC_DIR = os.path.join(WEB_DIR, "_static")
  43. # The directory where the utils file is located.
  44. WEB_UTILS_DIR = os.path.join(WEB_DIR, UTILS_DIR)
  45. # The directory where the assets are located.
  46. WEB_ASSETS_DIR = os.path.join(WEB_DIR, "public")
  47. # The sitemap config file.
  48. SITEMAP_CONFIG_FILE = os.path.join(WEB_DIR, "next-sitemap.config.js")
  49. # The node modules directory.
  50. NODE_MODULES = "node_modules"
  51. # The package lock file.
  52. PACKAGE_LOCK = "package-lock.json"
  53. # The pcversion app file.
  54. PCVERSION_APP_FILE = os.path.join(WEB_DIR, "pynecone.json")
  55. # Commands to run the app.
  56. # The frontend default port.
  57. FRONTEND_PORT = "3000"
  58. # The backend default port.
  59. BACKEND_PORT = "8000"
  60. # The backend api url.
  61. API_URL = "http://localhost:8000"
  62. # bun root location
  63. BUN_ROOT_PATH = "$HOME/.bun"
  64. # The default path where bun is installed.
  65. BUN_PATH = f"{BUN_ROOT_PATH}/bin/bun"
  66. # Command to install bun.
  67. INSTALL_BUN = f"curl -fsSL https://bun.sh/install | bash -s -- bun-v{MAX_BUN_VERSION}"
  68. # Default host in dev mode.
  69. BACKEND_HOST = "0.0.0.0"
  70. # The default timeout when launching the gunicorn server.
  71. TIMEOUT = 120
  72. # The command to run the backend in production mode.
  73. RUN_BACKEND_PROD = f"gunicorn --worker-class uvicorn.workers.UvicornH11Worker --preload --timeout {TIMEOUT} --log-level critical".split()
  74. RUN_BACKEND_PROD_WINDOWS = f"uvicorn --timeout-keep-alive {TIMEOUT}".split()
  75. # Socket.IO web server
  76. PING_INTERVAL = 25
  77. PING_TIMEOUT = 120
  78. # Compiler variables.
  79. # The extension for compiled Javascript files.
  80. JS_EXT = ".js"
  81. # The extension for python files.
  82. PY_EXT = ".py"
  83. # The expected variable name where the pc.App is stored.
  84. APP_VAR = "app"
  85. # The expected variable name where the API object is stored for deployment.
  86. API_VAR = "api"
  87. # The name of the router variable.
  88. ROUTER = "router"
  89. # The name of the socket variable.
  90. SOCKET = "socket"
  91. # The name of the variable to hold API results.
  92. RESULT = "result"
  93. # The name of the process variable.
  94. PROCESSING = "processing"
  95. # The name of the state variable.
  96. STATE = "state"
  97. # The name of the events variable.
  98. EVENTS = "events"
  99. # The name of the initial hydrate event.
  100. HYDRATE = "hydrate"
  101. # The name of the is_hydrated variable.
  102. IS_HYDRATED = "is_hydrated"
  103. # The name of the index page.
  104. INDEX_ROUTE = "index"
  105. # The name of the document root page.
  106. DOCUMENT_ROOT = "_document"
  107. # The name of the theme page.
  108. THEME = "theme"
  109. # The prefix used to create setters for state vars.
  110. SETTER_PREFIX = "set_"
  111. # The name of the frontend zip during deployment.
  112. FRONTEND_ZIP = "frontend.zip"
  113. # The name of the backend zip during deployment.
  114. BACKEND_ZIP = "backend.zip"
  115. # The name of the sqlite database.
  116. DB_NAME = "pynecone.db"
  117. # The sqlite url.
  118. DB_URL = f"sqlite:///{DB_NAME}"
  119. # The default title to show for Pynecone apps.
  120. DEFAULT_TITLE = "Pynecone App"
  121. # The default description to show for Pynecone apps.
  122. DEFAULT_DESCRIPTION = "A Pynecone app."
  123. # The default image to show for Pynecone apps.
  124. DEFAULT_IMAGE = "favicon.ico"
  125. # The default meta list to show for Pynecone apps.
  126. DEFAULT_META_LIST = []
  127. # The gitignore file.
  128. GITIGNORE_FILE = ".gitignore"
  129. # Files to gitignore.
  130. DEFAULT_GITIGNORE = {WEB_DIR, DB_NAME}
  131. # The name of the pynecone config module.
  132. CONFIG_MODULE = "pcconfig"
  133. # The python config file.
  134. CONFIG_FILE = f"{CONFIG_MODULE}{PY_EXT}"
  135. # The deployment URL.
  136. PRODUCTION_BACKEND_URL = "https://{username}-{app_name}.api.pynecone.app"
  137. # Token expiration time in seconds.
  138. TOKEN_EXPIRATION = 60 * 60
  139. # Env modes
  140. class Env(str, Enum):
  141. """The environment modes."""
  142. DEV = "dev"
  143. PROD = "prod"
  144. # Log levels
  145. class LogLevel(str, Enum):
  146. """The log levels."""
  147. DEBUG = "debug"
  148. INFO = "info"
  149. WARNING = "warning"
  150. ERROR = "error"
  151. CRITICAL = "critical"
  152. # Templates
  153. class Template(str, Enum):
  154. """The templates to use for the app."""
  155. DEFAULT = "default"
  156. COUNTER = "counter"
  157. class Endpoint(Enum):
  158. """Endpoints for the pynecone backend API."""
  159. PING = "ping"
  160. EVENT = "event"
  161. UPLOAD = "upload"
  162. def __str__(self) -> str:
  163. """Get the string representation of the endpoint.
  164. Returns:
  165. The path for the endpoint.
  166. """
  167. return f"/{self.value}"
  168. def get_url(self) -> str:
  169. """Get the URL for the endpoint.
  170. Returns:
  171. The full URL for the endpoint.
  172. """
  173. # Import here to avoid circular imports.
  174. from pynecone.config import get_config
  175. # Get the API URL from the config.
  176. config = get_config()
  177. url = "".join([config.api_url, str(self)])
  178. # The event endpoint is a websocket.
  179. if self == Endpoint.EVENT:
  180. # Replace the protocol with ws.
  181. url = url.replace("https://", "wss://").replace("http://", "ws://")
  182. # Return the url.
  183. return url
  184. class SocketEvent(Enum):
  185. """Socket events sent by the pynecone backend API."""
  186. PING = "ping"
  187. EVENT = "event"
  188. def __str__(self) -> str:
  189. """Get the string representation of the event name.
  190. Returns:
  191. The event name string.
  192. """
  193. return str(self.value)
  194. class Transports(Enum):
  195. """Socket transports used by the pynecone backend API."""
  196. POLLING_WEBSOCKET = "['polling', 'websocket']"
  197. WEBSOCKET_POLLING = "['websocket', 'polling']"
  198. WEBSOCKET_ONLY = "['websocket']"
  199. POLLING_ONLY = "['polling']"
  200. def __str__(self) -> str:
  201. """Get the string representation of the transports.
  202. Returns:
  203. The transports string.
  204. """
  205. return str(self.value)
  206. def get_transports(self) -> str:
  207. """Get the transports config for the backend.
  208. Returns:
  209. The transports config for the backend.
  210. """
  211. # Import here to avoid circular imports.
  212. from pynecone.config import get_config
  213. # Get the API URL from the config.
  214. config = get_config()
  215. return str(config.backend_transports)
  216. class RouteArgType(SimpleNamespace):
  217. """Type of dynamic route arg extracted from URI route."""
  218. # Typecast to str is needed for Enum to work.
  219. SINGLE = str("arg_single")
  220. LIST = str("arg_list")
  221. # the name of the backend var containing path and client information
  222. ROUTER_DATA = "router_data"
  223. class RouteVar(SimpleNamespace):
  224. """Names of variables used in the router_data dict stored in State."""
  225. CLIENT_IP = "ip"
  226. CLIENT_TOKEN = "token"
  227. HEADERS = "headers"
  228. PATH = "pathname"
  229. SESSION_ID = "sid"
  230. QUERY = "query"
  231. class RouteRegex(SimpleNamespace):
  232. """Regex used for extracting route args in route."""
  233. ARG = re.compile(r"\[(?!\.)([^\[\]]+)\]")
  234. # group return the catchall pattern (i.e. "[[..slug]]")
  235. CATCHALL = re.compile(r"(\[?\[\.{3}(?![0-9]).*\]?\])")
  236. # group return the arg name (i.e. "slug")
  237. STRICT_CATCHALL = re.compile(r"\[\.{3}([a-zA-Z_][\w]*)\]")
  238. # group return the arg name (i.e. "slug")
  239. OPT_CATCHALL = re.compile(r"\[\[\.{3}([a-zA-Z_][\w]*)\]\]")
  240. # 404 variables
  241. ROOT_404 = ""
  242. SLUG_404 = "[..._]"
  243. TITLE_404 = "404 - Not Found"
  244. FAVICON_404 = "favicon.ico"
  245. DESCRIPTION_404 = "The page was not found"
  246. # Color mode variables
  247. USE_COLOR_MODE = "useColorMode"
  248. COLOR_MODE = "colorMode"
  249. TOGGLE_COLOR_MODE = "toggleColorMode"
  250. # Server socket configuration variables
  251. CORS_ALLOWED_ORIGINS = "*"
  252. POLLING_MAX_HTTP_BUFFER_SIZE = 1000 * 1000