sveltekit-python-vercel 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -101,9 +101,11 @@ Using [Poetry](https://python-poetry.org/) to manage your virtual environments w
101
101
 
102
102
  [tool.poetry.dependencies]
103
103
  python = "^3.9"
104
- fastapi = "^0.95.1"
104
+ fastapi = "^0.95.2"
105
105
  uvicorn = "^0.22.0"
106
-
106
+
107
+ [tool.poetry.group.dev.dependencies]
108
+ watchfiles = "^0.19.0"
107
109
 
108
110
  [build-system]
109
111
  requires = ["poetry-core"]
@@ -204,12 +206,12 @@ Note:
204
206
  b: float
205
207
 
206
208
 
207
- async def POST(numberSet: NumberSet):
208
- return {"sum": float(numberSet.a) + float(numberSet.b)}
209
+ async def POST(data: NumberSet):
210
+ return {"sum": data.a + data.b}
209
211
 
210
212
 
211
- async def GET(a, b):
212
- return {"sum": float(a) + float(b)}
213
+ async def GET(a: float, b: float):
214
+ return {"sum": a + b}
213
215
 
214
216
  ```
215
217
 
@@ -228,8 +230,9 @@ Check out the awesome [sveltekit-modal](https://github.com/semicognitive/sveltek
228
230
 
229
231
  ## Possible future plans
230
232
 
233
+ - [X] Add hot reloading in dev mode
231
234
  - [ ] Generate endpoints (/api folder) automatically during build
232
235
  - [ ] Auto create requirements.txt from pyproject.toml (both related to vercel functions being checked/handled before build)
233
236
  - [ ] Add form actions
234
237
  - [ ] Add load functions
235
- - [ ] Add helper functions to automatically call API endpoints in project
238
+ - [ ] Add helper functions to automatically call API endpoints in project\
@@ -14,10 +14,9 @@ const get_pyServerEndpointAsString = (app_url, serve = false) => `
14
14
  fullURL = new URL('/api' + url.pathname, new URL('${app_url}')) + url.search;
15
15
  }
16
16
 
17
- console.log(\`Reached python endpoint of \${method} \${fullURL}\`)
17
+ console.log(\`PY: Reached python endpoint of \${method} \${fullURL}\`)
18
18
  let requestBody = await request.clone().text();
19
- console.log(\`Body: \${requestBody}\`);
20
- console.log(\`Content-Type: \${request.headers.get('content-type')}\`);
19
+ console.log(\`PY: Body: \${requestBody}\`);
21
20
 
22
21
  if (method === 'GET') {
23
22
  requestBody = null;
@@ -79,11 +78,11 @@ export async function sveltekit_python_vercel(opts = {}) {
79
78
  name: "vite-plugin-sveltekit_python-build",
80
79
  apply: "build",
81
80
  async configResolved(config) {
82
- console.log("BUILD DEBUG");
83
- console.log("ROOT PATH: " + config.root);
84
- console.log("LOADED VERCEL URL: " + loadEnv("", config.root, "").VERCEL_URL);
81
+ console.log("PY: BUILD DEBUG");
82
+ console.log("PY: ROOT PATH: " + config.root);
83
+ console.log("PY: LOADED VERCEL URL: " + loadEnv("", config.root, "").VERCEL_URL);
85
84
  const packagelocation = path.join(config.root, "node_modules", "sveltekit-python-vercel", "esm/src/vite");
86
- console.log("PACKAGE LOCATION: " + packagelocation);
85
+ console.log("PY: PACKAGE LOCATION: " + packagelocation);
87
86
  const python_path = opts.python_path ?? (await which("python3"));
88
87
  await run$ `cd ${packagelocation}`;
89
88
  await run$ `${python_path} ${packagelocation}/sveltekit_python_vercel/build.py --root ${config.root}`;
@@ -95,7 +94,7 @@ export async function sveltekit_python_vercel(opts = {}) {
95
94
  const api_url = path.join(httpPrefix + loadEnv("", config.root, "").VERCEL_URL);
96
95
  // get current Vercel deploy URL
97
96
  sveltekit_url = new URL(api_url);
98
- console.log("Build API URL: " + sveltekit_url.toString());
97
+ console.log("PY: Build API URL: " + sveltekit_url.toString());
99
98
  },
100
99
  };
101
100
  const plugin_py_server_endpoint_serve = {
@@ -1,7 +1,7 @@
1
- import os
2
1
  import glob
3
2
  import importlib
4
3
  import importlib.util
4
+ import os
5
5
  from pathlib import Path
6
6
 
7
7
  from fastapi import FastAPI, Request
@@ -27,27 +27,22 @@ for module_path in glob.glob('./**/+server.py', recursive=True):
27
27
  api_route = api_route.replace('[', '{').replace(']', '}')
28
28
 
29
29
  mod = importlib.import_module(module_name, module_package)
30
-
31
- if hasattr(mod, 'GET'):
32
- app.add_api_route(api_route, mod.GET, methods=["GET"])
33
- print(f"PYTHON ENDPOINT: Added {module_path} [GET] at {api_route}")
34
-
35
- if hasattr(mod, 'POST'):
36
- app.add_api_route(api_route, mod.POST, methods=["POST"])
37
- print(f"PYTHON ENDPOINT: Added {module_path} [POST] at {api_route}")
38
-
39
- if hasattr(mod, 'PATCH'):
40
- app.add_api_route(api_route, mod.PATCH, methods=["PATCH"])
41
- print(f"PYTHON ENDPOINT: Added {module_path} [PATCH] at {api_route}")
42
-
43
- if hasattr(mod, 'PUT'):
44
- app.add_api_route(api_route, mod.PUT, methods=["PUT"])
45
- print(f"PYTHON ENDPOINT: Added {module_path} [PUT] at {api_route}")
46
-
47
- if hasattr(mod, 'DELETE'):
48
- app.add_api_route(api_route, mod.DELETE, methods=["DELETE"])
49
- print(f"PYTHON ENDPOINT: Added {module_path} [DELETE] at {api_route}")
50
-
30
+
31
+ # Add endpoints
32
+ for method in ["GET", "POST", "PATCH", "PUT", "DELETE"]:
33
+
34
+ # Check for duplicate methods
35
+ if hasattr(mod, method) and hasattr(mod, method.lower()):
36
+ raise Exception(
37
+ f"Duplicate method {method} and {method.lower()} in {api_route}"
38
+ )
39
+
40
+ elif hasattr(mod, method):
41
+ app.add_api_route(api_route, getattr(mod, method), methods=[method])
42
+ print(f"PYTHON ENDPOINT: Added {module_path} [{method}] at {api_route}")
43
+ elif hasattr(mod, method.lower()):
44
+ app.add_api_route(api_route, getattr(mod, method.lower()), methods=[method])
45
+ print(f"PYTHON ENDPOINT: Added {module_path} [{method}] at {api_route}")
51
46
 
52
47
  @app.exception_handler(Exception)
53
48
  async def unicorn_exception_handler(request: Request, exc: Exception):
@@ -1,14 +1,12 @@
1
- import uvicorn
2
1
  import argparse
3
- import os
2
+ import glob
4
3
  import importlib
5
4
  import importlib.util
6
- import glob
7
5
  import shutil
8
6
  from pathlib import Path
9
7
 
10
- from fastapi import FastAPI, Request
11
- from fastapi.responses import JSONResponse
8
+ import uvicorn
9
+ from fastapi import FastAPI
12
10
 
13
11
  parser = argparse.ArgumentParser(description="Run Sveltekit Python Server")
14
12
  parser.add_argument("--host", default="0.0.0.0", help="Server hostname")
@@ -18,62 +16,64 @@ args = parser.parse_args()
18
16
 
19
17
  app = FastAPI()
20
18
 
21
- def app_factory():
22
- return app # return the app object
19
+ root_dir = Path(args.root).absolute()
20
+
21
+ api_dir = Path("./sveltekit_python_vercel").absolute()
22
+
23
+ route_dir = root_dir.joinpath("src/routes")
24
+
25
+ watch_modules = [] # list of modules to watch for changes
26
+
27
+ for module_path in glob.glob(
28
+ route_dir.joinpath("**/+server.py").as_posix(), recursive=True
29
+ ):
30
+ abs_module_path = Path(module_path).absolute()
31
+
32
+ watch_modules.append(abs_module_path.parent.as_posix())
33
+
34
+ api_route = api_dir.joinpath(abs_module_path.relative_to(root_dir / "src/routes"))
35
+
36
+ if not api_route.parent.exists():
37
+ api_route.parent.mkdir(parents=True)
38
+
39
+ # copy module path to api_route
40
+ shutil.copy(module_path, api_route.parent)
41
+
42
+ module_name = api_route.stem
43
+
44
+ spec = importlib.util.spec_from_file_location(module_name, api_route)
45
+ mod = importlib.util.module_from_spec(spec)
46
+ spec.loader.exec_module(mod)
47
+
48
+ # Get the relative path of the module from the API directory
49
+ rel_path = api_route.relative_to(api_dir)
50
+
51
+ # Convert the relative path to a string and remove the file extension
52
+ api_path = f"/{rel_path.parent}"
53
+
54
+ # Replace square brackets with curly brackets
55
+ api_path = api_path.replace("[", "{").replace("]", "}")
56
+
57
+ # Add endpoints
58
+ for method in ["GET", "POST", "PATCH", "PUT", "DELETE"]:
59
+ # Check for duplicate methods
60
+ if hasattr(mod, method) and hasattr(mod, method.lower()):
61
+ raise Exception(
62
+ f"Duplicate method {method} and {method.lower()} in {api_route}"
63
+ )
64
+ elif hasattr(mod, method):
65
+ app.add_api_route(api_path, getattr(mod, method), methods=[method])
66
+ elif hasattr(mod, method.lower()):
67
+ app.add_api_route(api_path, getattr(mod, method.lower()), methods=[method])
68
+
23
69
 
24
70
  if __name__ == "__main__":
25
-
26
- root_dir = Path(args.root).absolute()
27
- api_dir = Path("./sveltekit_python_vercel").absolute()
28
-
29
- # Add all +server.py routes to web_app
30
- for module_path in glob.glob(str(root_dir / 'src/routes/**/+server.py'), recursive=True):
31
-
32
- # replace the root_dir with api_dir
33
- api_route = api_dir / Path(module_path).absolute().relative_to(root_dir/ "src/routes")
34
-
35
- if not api_route.parent.exists():
36
- api_route.parent.mkdir(parents=True)
37
-
38
- # copy module path to api_route
39
- shutil.copy(module_path, api_route.parent)
40
- print(f"PYTHON ENDPOINT: Copied {module_path} to {api_route.parent}")
41
-
42
- # Get the module name from the module path
43
- module_name = api_route.stem
44
-
45
- # Import the module dynamically
46
- spec = importlib.util.spec_from_file_location(module_name, api_route)
47
- mod = importlib.util.module_from_spec(spec)
48
- spec.loader.exec_module(mod)
49
-
50
- # Get the relative path of the module from the API directory
51
- rel_path = api_route.relative_to(api_dir)
52
- # Convert the relative path to a string and remove the file extension
53
- api_path = "/" + str(rel_path.parent)
54
-
55
- # Replace square brackets with curly brackets
56
- api_path = api_path.replace('[', '{').replace(']', '}')
57
-
58
- print("ADDING API PATH:", rel_path, api_path)
59
-
60
- if hasattr(mod, 'GET'):
61
- app.add_api_route(api_path, mod.GET, methods=["GET"])
62
-
63
- if hasattr(mod, 'POST'):
64
- app.add_api_route(api_path, mod.POST, methods=["POST"])
65
-
66
- if hasattr(mod, 'PATCH'):
67
- app.add_api_route(api_path, mod.PATCH, methods=["PATCH"])
68
-
69
- if hasattr(mod, 'PUT'):
70
- app.add_api_route(api_path, mod.PUT, methods=["PUT"])
71
-
72
- if hasattr(mod, 'DELETE'):
73
- app.add_api_route(api_path, mod.DELETE, methods=["DELETE"])
74
-
75
-
76
- config = uvicorn.Config(app_factory, host=args.host, port=args.port, log_level="info", factory=True)
77
- server = uvicorn.Server(config)
78
- print(f"Hosting on http://{args.host}:{args.port}")
79
- server.run()
71
+ uvicorn.run(
72
+ "sveltekit_python_vercel.serve:app",
73
+ host=args.host,
74
+ port=args.port,
75
+ log_level="info",
76
+ reload=True,
77
+ reload_includes=[*set(watch_modules)],
78
+ reload_excludes=[api_dir.as_posix()],
79
+ )
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "module": "./esm/mod.js",
3
3
  "types": "./types/mod.d.ts",
4
4
  "name": "sveltekit-python-vercel",
5
- "version": "v0.3.0",
5
+ "version": "v0.4.0",
6
6
  "description": "Write Sveltekit server endpoints in Python and seamlessly deploy to Vercel",
7
7
  "repository": {
8
8
  "type": "git",