mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-30 17:53:31 -04:00 
			
		
		
		
	* fix favorite color issue * db and models for comments * rename files * initial UI for comments * fix format * import / export * fixes #428 * format Co-authored-by: hay-kot <hay-kot@pm.me>
		
			
				
	
	
		
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import re
 | |
| from enum import Enum
 | |
| from itertools import groupby
 | |
| from pathlib import Path
 | |
| 
 | |
| import slugify
 | |
| from fastapi import FastAPI
 | |
| from humps import camelize
 | |
| from jinja2 import Template
 | |
| from mealie.app import app
 | |
| from pydantic import BaseModel
 | |
| 
 | |
| CWD = Path(__file__).parent
 | |
| OUT_DIR = CWD / "output"
 | |
| OUT_FILE = OUT_DIR / "app_routes.py"
 | |
| 
 | |
| JS_DIR = OUT_DIR / "javascriptAPI"
 | |
| JS_OUT_FILE = JS_DIR / "apiRoutes.js"
 | |
| TEMPLATES_DIR = CWD / "templates"
 | |
| 
 | |
| PYTEST_TEMPLATE = TEMPLATES_DIR / "pytest_routes.j2"
 | |
| JS_REQUESTS = TEMPLATES_DIR / "js_requests.j2"
 | |
| JS_ROUTES = TEMPLATES_DIR / "js_routes.j2"
 | |
| JS_INDEX = TEMPLATES_DIR / "js_index.j2"
 | |
| 
 | |
| JS_DIR.mkdir(exist_ok=True, parents=True)
 | |
| 
 | |
| 
 | |
| class RouteObject:
 | |
|     def __init__(self, route_string) -> None:
 | |
|         self.prefix = "/" + route_string.split("/")[1]
 | |
|         self.route = route_string.replace(self.prefix, "")
 | |
|         self.js_route = self.route.replace("{", "${")
 | |
|         self.parts = route_string.split("/")[1:]
 | |
|         self.var = re.findall(r"\{(.*?)\}", route_string)
 | |
|         self.is_function = "{" in self.route
 | |
|         self.router_slug = slugify.slugify("_".join(self.parts[1:]), separator="_")
 | |
|         self.router_camel = camelize(self.router_slug)
 | |
| 
 | |
|     def __repr__(self) -> str:
 | |
|         return f"""Route: {self.route}
 | |
| Parts: {self.parts}
 | |
| Function: {self.is_function}
 | |
| Var: {self.var}
 | |
| Slug: {self.router_slug}
 | |
| """
 | |
| 
 | |
| 
 | |
| class RequestType(str, Enum):
 | |
|     get = "get"
 | |
|     put = "put"
 | |
|     post = "post"
 | |
|     patch = "patch"
 | |
|     delete = "delete"
 | |
| 
 | |
| 
 | |
| class HTTPRequest(BaseModel):
 | |
|     request_type: RequestType
 | |
|     description: str = ""
 | |
|     summary: str
 | |
|     tags: list[str]
 | |
| 
 | |
|     @property
 | |
|     def summary_camel(self):
 | |
|         return camelize(self.summary)
 | |
| 
 | |
|     @property
 | |
|     def js_docs(self):
 | |
|         return self.description.replace("\n", "  \n  * ")
 | |
| 
 | |
| 
 | |
| class PathObject(BaseModel):
 | |
|     route_object: RouteObject
 | |
|     http_verbs: list[HTTPRequest]
 | |
| 
 | |
|     class Config:
 | |
|         arbitrary_types_allowed = True
 | |
| 
 | |
| 
 | |
| def get_path_objects(app: FastAPI):
 | |
|     paths = []
 | |
| 
 | |
|     for key, value in app.openapi().items():
 | |
|         if key == "paths":
 | |
|             for key, value in value.items():
 | |
| 
 | |
|                 paths.append(
 | |
|                     PathObject(
 | |
|                         route_object=RouteObject(key),
 | |
|                         http_verbs=[HTTPRequest(request_type=k, **v) for k, v in value.items()],
 | |
|                     )
 | |
|                 )
 | |
| 
 | |
|     return paths
 | |
| 
 | |
| 
 | |
| def read_template(file: Path):
 | |
|     with open(file, "r") as f:
 | |
|         return f.read()
 | |
| 
 | |
| 
 | |
| def generate_template(app):
 | |
|     paths = get_path_objects(app)
 | |
| 
 | |
|     static_paths = [x.route_object for x in paths if not x.route_object.is_function]
 | |
|     function_paths = [x.route_object for x in paths if x.route_object.is_function]
 | |
| 
 | |
|     static_paths.sort(key=lambda x: x.router_slug)
 | |
|     function_paths.sort(key=lambda x: x.router_slug)
 | |
| 
 | |
|     template = Template(read_template(PYTEST_TEMPLATE))
 | |
|     content = template.render(paths={"prefix": "/api", "static_paths": static_paths, "function_paths": function_paths})
 | |
|     with open(OUT_FILE, "w") as f:
 | |
|         f.write(content)
 | |
| 
 | |
|     template = Template(read_template(JS_ROUTES))
 | |
|     content = template.render(
 | |
|         paths={"prefix": "/api", "static_paths": static_paths, "function_paths": function_paths, "all_paths": paths}
 | |
|     )
 | |
|     with open(JS_OUT_FILE, "w") as f:
 | |
|         f.write(content)
 | |
| 
 | |
|     all_tags = []
 | |
|     for k, g in groupby(paths, lambda x: x.http_verbs[0].tags[0]):
 | |
|         template = Template(read_template(JS_REQUESTS))
 | |
|         content = template.render(paths={"all_paths": list(g), "export_name": camelize(k)})
 | |
| 
 | |
|         all_tags.append(camelize(k))
 | |
| 
 | |
|         with open(JS_DIR.joinpath(camelize(k) + ".js"), "w") as f:
 | |
|             f.write(content)
 | |
| 
 | |
|     template = Template(read_template(JS_INDEX))
 | |
|     content = template.render(files={"files": all_tags})
 | |
| 
 | |
|     with open(JS_DIR.joinpath("index.js"), "w") as f:
 | |
|         f.write(content)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     generate_template(app)
 |