skeleton-framework 0.1.0__py3-none-any.whl

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.
Files changed (93) hide show
  1. skeleton/__init__.py +0 -0
  2. skeleton/cli.py +151 -0
  3. skeleton/client.py +269 -0
  4. skeleton/infrastructure/__init__.py +1 -0
  5. skeleton/infrastructure/bootstrap/__init__.py +0 -0
  6. skeleton/infrastructure/bootstrap/src/__init__.py +0 -0
  7. skeleton/infrastructure/bootstrap/src/commands/__init__.py +0 -0
  8. skeleton/infrastructure/bootstrap/src/commands/client/__init__.py +0 -0
  9. skeleton/infrastructure/bootstrap/src/commands/client/init.py +486 -0
  10. skeleton/infrastructure/bootstrap/src/commands/client/install.py +113 -0
  11. skeleton/infrastructure/bootstrap/src/commands/dev/__init__.py +0 -0
  12. skeleton/infrastructure/bootstrap/src/commands/dev/build.py +80 -0
  13. skeleton/infrastructure/bootstrap/src/commands/dev/init.py +80 -0
  14. skeleton/infrastructure/bootstrap/src/commands/dev/install.py +168 -0
  15. skeleton/infrastructure/bootstrap/src/commands/dev/pack.py +55 -0
  16. skeleton/infrastructure/bootstrap/src/config.py +54 -0
  17. skeleton/infrastructure/bootstrap/src/copy.py +56 -0
  18. skeleton/infrastructure/bootstrap/src/load.py +221 -0
  19. skeleton/infrastructure/bootstrap/src/templates/app/backend/requirements.txt +1 -0
  20. skeleton/infrastructure/bootstrap/src/templates/app/backend/routes.json +10 -0
  21. skeleton/infrastructure/bootstrap/src/templates/app/backend/src/__init__.py +0 -0
  22. skeleton/infrastructure/bootstrap/src/templates/app/backend/src/main.py +35 -0
  23. skeleton/infrastructure/bootstrap/src/templates/app/frontend/package.json +21 -0
  24. skeleton/infrastructure/bootstrap/src/templates/app/frontend/skeleton-config.json +29 -0
  25. skeleton/infrastructure/bootstrap/src/templates/app/frontend/src/index.html +16 -0
  26. skeleton/infrastructure/bootstrap/src/templates/app/frontend/src/main.tsx +15 -0
  27. skeleton/infrastructure/bootstrap/src/templates/app/frontend/src/static/css/styles.css +28 -0
  28. skeleton/infrastructure/bootstrap/src/templates/app/frontend/src/static/img/skeleton.png +0 -0
  29. skeleton/infrastructure/bootstrap/src/templates/app/frontend/src/static/js/script.js +1 -0
  30. skeleton/infrastructure/bootstrap/src/templates/app/frontend/tsconfig.json +90 -0
  31. skeleton/infrastructure/bootstrap/src/templates/config/.gitignore +21 -0
  32. skeleton/infrastructure/bootstrap/src/templates/config/skeleton-dependencies.json +21 -0
  33. skeleton/infrastructure/bootstrap/src/templates/config/skeleton-layout.json +11 -0
  34. skeleton/infrastructure/bootstrap/src/templates/config/skeleton-schemas.json +20 -0
  35. skeleton/infrastructure/bootstrap/src/templates/config/skeleton-servers.json +16 -0
  36. skeleton/infrastructure/common/__init__.py +1 -0
  37. skeleton/infrastructure/common/config.json +8 -0
  38. skeleton/infrastructure/common/src/__init__.py +0 -0
  39. skeleton/infrastructure/common/src/config.py +37 -0
  40. skeleton/infrastructure/common/src/constants.py +4 -0
  41. skeleton/infrastructure/common/src/context.py +15 -0
  42. skeleton/infrastructure/common/src/env.py +12 -0
  43. skeleton/infrastructure/common/src/layout.py +68 -0
  44. skeleton/infrastructure/common/src/loader.py +8 -0
  45. skeleton/infrastructure/common/src/repository.py +12 -0
  46. skeleton/infrastructure/common/src/utils.py +26 -0
  47. skeleton/infrastructure/gateway/__init__.py +0 -0
  48. skeleton/infrastructure/gateway/settings/proxy.json +24 -0
  49. skeleton/infrastructure/gateway/settings/services.json +10 -0
  50. skeleton/infrastructure/gateway/src/__init__.py +0 -0
  51. skeleton/infrastructure/gateway/src/app.py +98 -0
  52. skeleton/infrastructure/gateway/src/client.py +68 -0
  53. skeleton/infrastructure/gateway/src/config.py +29 -0
  54. skeleton/infrastructure/gateway/src/context.py +31 -0
  55. skeleton/infrastructure/gateway/src/headers.py +17 -0
  56. skeleton/infrastructure/gateway/src/lifespan.py +17 -0
  57. skeleton/infrastructure/gateway/src/loader.py +113 -0
  58. skeleton/infrastructure/gateway/src/logging.py +37 -0
  59. skeleton/infrastructure/gateway/src/main.py +139 -0
  60. skeleton/infrastructure/gateway/src/parser.py +59 -0
  61. skeleton/infrastructure/gateway/src/registry.py +30 -0
  62. skeleton/infrastructure/gateway/src/reverseproxy.py +54 -0
  63. skeleton/infrastructure/gateway/src/router.py +74 -0
  64. skeleton/infrastructure/gateway/src/schemas.py +21 -0
  65. skeleton/infrastructure/gateway/src/service.py +123 -0
  66. skeleton/infrastructure/gateway/src/utils.py +48 -0
  67. skeleton/infrastructure/gateway/src/validation.py +89 -0
  68. skeleton/infrastructure/layout.json +12 -0
  69. skeleton/infrastructure/runners/__init__.py +0 -0
  70. skeleton/infrastructure/runners/src/__init__.py +0 -0
  71. skeleton/infrastructure/runners/src/actions.py +4 -0
  72. skeleton/infrastructure/runners/src/browser.py +18 -0
  73. skeleton/infrastructure/runners/src/cmd.py +7 -0
  74. skeleton/infrastructure/runners/src/command.py +7 -0
  75. skeleton/infrastructure/runners/src/frontend.py +35 -0
  76. skeleton/infrastructure/runners/src/gateway.py +104 -0
  77. skeleton/infrastructure/runners/src/hook.py +53 -0
  78. skeleton/infrastructure/runners/src/main.py +78 -0
  79. skeleton/infrastructure/runners/src/packages.py +35 -0
  80. skeleton/infrastructure/runners/src/parser.py +84 -0
  81. skeleton/infrastructure/runners/src/process.py +99 -0
  82. skeleton/infrastructure/runners/src/services.py +16 -0
  83. skeleton/infrastructure/runners/src/utils.py +6 -0
  84. skeleton/infrastructure/runners/src/validation.py +28 -0
  85. skeleton/packages/.skeleton/skeleton-cli-1.0.0.tgz +0 -0
  86. skeleton/packages/.skeleton/skeleton-webpack-1.0.0.tgz +0 -0
  87. skeleton/root.py +234 -0
  88. skeleton_framework-0.1.0.dist-info/METADATA +440 -0
  89. skeleton_framework-0.1.0.dist-info/RECORD +93 -0
  90. skeleton_framework-0.1.0.dist-info/WHEEL +5 -0
  91. skeleton_framework-0.1.0.dist-info/entry_points.txt +2 -0
  92. skeleton_framework-0.1.0.dist-info/licenses/LICENSE +146 -0
  93. skeleton_framework-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,80 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+
5
+ from pathlib import Path
6
+ def dev_init(
7
+ framework_root: Path,
8
+ ) -> None:
9
+
10
+ framework_root = framework_root.resolve()
11
+
12
+ # ---------------------------------------------------------
13
+ # Validate framework package configuration
14
+ # ---------------------------------------------------------
15
+
16
+ pyproject = framework_root / "pyproject.toml"
17
+
18
+ if not pyproject.is_file():
19
+
20
+ raise FileNotFoundError(
21
+ f"Framework Python package configuration not found: "
22
+ f"{pyproject}"
23
+ )
24
+
25
+ # ---------------------------------------------------------
26
+ # Generate framework development requirements
27
+ # ---------------------------------------------------------
28
+
29
+ requirements = framework_root / "requirements.txt"
30
+
31
+ if not requirements.is_file():
32
+
33
+ print(
34
+ f"INFO: Creating framework requirements file: "
35
+ f"{requirements}"
36
+ )
37
+
38
+ requirements.write_text(
39
+ "build\n"
40
+ "twine\n",
41
+ encoding="utf-8",
42
+ )
43
+
44
+ # ---------------------------------------------------------
45
+ # Create framework root virtual environment
46
+ # ---------------------------------------------------------
47
+
48
+ venv = framework_root / ".venv"
49
+
50
+ if not venv.is_dir():
51
+
52
+ print(
53
+ f"INFO: Creating framework virtual environment: "
54
+ f"{venv}"
55
+ )
56
+
57
+ subprocess.run(
58
+ [
59
+ sys.executable,
60
+ "-m",
61
+ "venv",
62
+ str(venv),
63
+ ],
64
+ cwd=framework_root,
65
+ check=True,
66
+ )
67
+
68
+ python = (
69
+ venv / "Scripts" / "python.exe"
70
+ if os.name == "nt"
71
+ else venv / "bin" / "python"
72
+ )
73
+
74
+ if not python.is_file():
75
+
76
+ raise FileNotFoundError(
77
+ f"Framework Python executable not found: {python}"
78
+ )
79
+
80
+ print("INFO: Framework development initialization complete")
@@ -0,0 +1,168 @@
1
+ import os, sys
2
+ import subprocess
3
+
4
+ from pathlib import Path
5
+
6
+ def dev_install(
7
+ framework_root: Path,
8
+ ) -> None:
9
+
10
+ framework_root = framework_root.resolve()
11
+
12
+ # ---------------------------------------------------------
13
+ # Install framework root development requirements
14
+ # ---------------------------------------------------------
15
+
16
+ requirements = framework_root / "requirements.txt"
17
+
18
+ if not requirements.is_file():
19
+
20
+ raise FileNotFoundError(
21
+ f"Framework Python requirements not found: "
22
+ f"{requirements}"
23
+ )
24
+
25
+ venv = framework_root / ".venv"
26
+
27
+ if not venv.is_dir():
28
+
29
+ raise FileNotFoundError(
30
+ f"Framework virtual environment not found: {venv}. "
31
+ "Run --dev-init first."
32
+ )
33
+
34
+ python = (
35
+ venv / "Scripts" / "python.exe"
36
+ if os.name == "nt"
37
+ else venv / "bin" / "python"
38
+ )
39
+
40
+ if not python.is_file():
41
+
42
+ raise FileNotFoundError(
43
+ f"Framework Python executable not found: {python}"
44
+ )
45
+
46
+ print(
47
+ f"INFO: Installing framework Python requirements: "
48
+ f"{requirements}"
49
+ )
50
+
51
+ subprocess.run(
52
+ [
53
+ str(python),
54
+ "-m",
55
+ "pip",
56
+ "install",
57
+ "-r",
58
+ str(requirements),
59
+ ],
60
+ cwd=framework_root,
61
+ check=True,
62
+ )
63
+
64
+ # ---------------------------------------------------------
65
+ # Validate framework package configuration
66
+ # ---------------------------------------------------------
67
+
68
+ pyproject = framework_root / "pyproject.toml"
69
+
70
+ if not pyproject.is_file():
71
+
72
+ raise FileNotFoundError(
73
+ f"Framework Python package configuration not found: "
74
+ f"{pyproject}"
75
+ )
76
+
77
+ # ---------------------------------------------------------
78
+ # Create framework gateway environment
79
+ # ---------------------------------------------------------
80
+
81
+ gateway_root = (
82
+ framework_root
83
+ / "skeleton"
84
+ / "infrastructure"
85
+ / "gateway"
86
+ )
87
+
88
+ venv = gateway_root / ".venv"
89
+
90
+ if not venv.is_dir():
91
+
92
+ print(f"INFO: Creating framework virtual environment: {venv}")
93
+
94
+ subprocess.run(
95
+ [
96
+ sys.executable,
97
+ "-m",
98
+ "venv",
99
+ str(venv),
100
+ ],
101
+ cwd=framework_root,
102
+ check=True,
103
+ )
104
+
105
+ python = (
106
+ venv / "Scripts" / "python.exe"
107
+ if os.name == "nt"
108
+ else venv / "bin" / "python"
109
+ )
110
+
111
+ if not python.is_file():
112
+
113
+ raise FileNotFoundError(
114
+ f"Framework Python executable not found: {python}"
115
+ )
116
+
117
+ # ---------------------------------------------------------
118
+ # Install Skeleton and its declared Python dependencies
119
+ # ---------------------------------------------------------
120
+
121
+ print(
122
+ f"INFO: Installing Skeleton framework in editable mode: "
123
+ f"{framework_root}"
124
+ )
125
+
126
+ subprocess.run(
127
+ [
128
+ str(python),
129
+ "-m",
130
+ "pip",
131
+ "install",
132
+ "-e",
133
+ str(framework_root),
134
+ ],
135
+ cwd=framework_root,
136
+ check=True,
137
+ )
138
+
139
+ # ---------------------------------------------------------
140
+ # Install framework Node.js development dependencies
141
+ # ---------------------------------------------------------
142
+
143
+ package_json = framework_root / "package.json"
144
+
145
+ if not package_json.is_file():
146
+
147
+ raise FileNotFoundError(
148
+ f"Framework package manifest not found: {package_json}"
149
+ )
150
+
151
+ npm = (
152
+ "npm.cmd"
153
+ if os.name == "nt"
154
+ else "npm"
155
+ )
156
+
157
+ print(
158
+ f"INFO: Installing framework Node.js dependencies: "
159
+ f"{framework_root}"
160
+ )
161
+
162
+ subprocess.run(
163
+ [npm, "install"],
164
+ cwd=framework_root,
165
+ check=True,
166
+ )
167
+
168
+ print("INFO: Framework development installation complete")
@@ -0,0 +1,55 @@
1
+ import os, shutil
2
+ import subprocess
3
+
4
+ from pathlib import Path
5
+
6
+ def dev_pack(framework_root: Path) -> None:
7
+
8
+ framework_root = framework_root.resolve()
9
+
10
+ packages_root = framework_root / "skeleton" / "packages"
11
+ artifacts_root = packages_root / ".skeleton"
12
+
13
+ npm = "npm.cmd" if os.name == "nt" else "npm"
14
+
15
+ # 1. Build both packages from the framework root.
16
+ subprocess.run(
17
+ [npm, "run", "packages:build"],
18
+ cwd=framework_root,
19
+ check=True,
20
+ )
21
+
22
+ # 2. Recreate the predictable output directory.
23
+ if artifacts_root.exists():
24
+
25
+ shutil.rmtree(artifacts_root)
26
+
27
+ artifacts_root.mkdir(parents=True)
28
+
29
+ # 3. Pack webpack first, then the CLI.
30
+ for name in ("webpack", "cli"):
31
+
32
+ package_root = packages_root / name
33
+
34
+ if not (package_root / "package.json").is_file():
35
+
36
+ raise FileNotFoundError(
37
+ f"Package manifest not found: "
38
+ f"{package_root / 'package.json'}"
39
+ )
40
+
41
+ subprocess.run(
42
+ [
43
+ npm,
44
+ "pack",
45
+ "--pack-destination",
46
+ str(artifacts_root),
47
+ ],
48
+ cwd=package_root,
49
+ check=True,
50
+ )
51
+
52
+ print(
53
+ f"\nSkeleton packages created in:\n"
54
+ f"{artifacts_root}"
55
+ )
@@ -0,0 +1,54 @@
1
+ import shutil
2
+
3
+ from pathlib import Path
4
+
5
+ def config(
6
+ framework_root: Path,
7
+ project_root: Path,
8
+ ) -> None:
9
+
10
+ templates = (
11
+ framework_root
12
+ / "skeleton"
13
+ / "infrastructure"
14
+ / "bootstrap"
15
+ / "src"
16
+ / "templates"
17
+ / "config"
18
+ )
19
+
20
+ if not templates.is_dir():
21
+
22
+ raise FileNotFoundError(
23
+ f"Configuration templates not found: {templates}"
24
+ )
25
+
26
+ project_root = project_root.resolve()
27
+
28
+ project_root.mkdir(
29
+ parents=True,
30
+ exist_ok=True,
31
+ )
32
+
33
+ for template in templates.iterdir():
34
+
35
+ destination = project_root / template.name
36
+
37
+ if destination.exists():
38
+
39
+ print(
40
+ f"INFO: Preserving existing file: {destination}"
41
+ )
42
+ continue
43
+
44
+ if template.is_dir():
45
+
46
+ shutil.copytree(template, destination)
47
+
48
+ else:
49
+
50
+ shutil.copy2(template, destination)
51
+
52
+ print(f"INFO: Created: {destination}")
53
+
54
+ print("INFO: Configuration complete")
@@ -0,0 +1,56 @@
1
+ import shutil
2
+
3
+ from pathlib import Path
4
+
5
+ def copy_template(source: Path, target: Path) -> None:
6
+
7
+ target.mkdir(parents=True, exist_ok=True)
8
+
9
+ for item in source.iterdir():
10
+
11
+ destination = target / item.name
12
+
13
+ if destination.exists():
14
+
15
+ if item.is_dir() and destination.is_dir():
16
+ copy_template(item, destination)
17
+
18
+ continue
19
+
20
+ if item.is_dir():
21
+ shutil.copytree(item, destination)
22
+
23
+ else:
24
+ shutil.copy2(item, destination)
25
+
26
+ def copy_app_template(
27
+ source: Path,
28
+ target: Path,
29
+ frontend: str,
30
+ backend: str,
31
+ ) -> None:
32
+
33
+ target.mkdir(parents=True, exist_ok=True)
34
+
35
+ directories = {
36
+ "frontend": frontend,
37
+ "backend": backend,
38
+ }
39
+
40
+ for item in source.iterdir():
41
+
42
+ name = directories.get(item.name, item.name)
43
+ destination = target / name
44
+
45
+ if destination.exists():
46
+
47
+ if item.is_dir() and destination.is_dir():
48
+ copy_template(item, destination)
49
+
50
+ continue
51
+
52
+ if item.is_dir():
53
+ shutil.copytree(item, destination)
54
+
55
+ else:
56
+ shutil.copy2(item, destination)
@@ -0,0 +1,221 @@
1
+ import json
2
+
3
+ from pathlib import Path
4
+
5
+ def load_layout(path: Path) -> dict[str, str]:
6
+
7
+ if not path.is_file():
8
+
9
+ raise FileNotFoundError(
10
+ f"Project layout configuration not found: {path}"
11
+ )
12
+
13
+ with path.open("r", encoding="utf-8") as file:
14
+
15
+ config = json.load(file)
16
+
17
+ try:
18
+
19
+ app = config["project"]["app"]
20
+ frontend = config["frontend"]["directory"]
21
+ backend = config["backend"]["directory"]
22
+
23
+ except (KeyError, TypeError) as error:
24
+ raise ValueError(
25
+ f"Invalid project layout configuration: {path}"
26
+ ) from error
27
+
28
+ values = {
29
+ "project.app": app,
30
+ "frontend.directory": frontend,
31
+ "backend.directory": backend,
32
+ }
33
+
34
+ for key, value in values.items():
35
+
36
+ if (
37
+ not isinstance(value, str)
38
+ or not value.strip()
39
+ or Path(value).is_absolute()
40
+ or len(Path(value).parts) != 1
41
+ or value in (".", "..")
42
+ ):
43
+ raise ValueError(
44
+ f"Invalid directory name for '{key}': {value!r}"
45
+ )
46
+
47
+ return {
48
+ "app": app,
49
+ "frontend": frontend,
50
+ "backend": backend,
51
+ }
52
+
53
+ # def load_dependencies(path: Path) -> dict:
54
+
55
+ # if not path.is_file():
56
+ # raise FileNotFoundError(
57
+ # f"Dependencies configuration not found: {path}"
58
+ # )
59
+
60
+ # with path.open(
61
+ # "r",
62
+ # encoding="utf-8",
63
+ # ) as file:
64
+ # config = json.load(file)
65
+
66
+ # if not isinstance(config, dict):
67
+ # raise ValueError(
68
+ # f"Invalid dependencies configuration: {path}"
69
+ # )
70
+
71
+ # frontend = config.get("frontend")
72
+ # backend = config.get("backend")
73
+
74
+ # if not isinstance(frontend, dict):
75
+ # raise ValueError(
76
+ # f"Invalid frontend configuration: {path}"
77
+ # )
78
+
79
+ # packages = frontend.get("packages")
80
+
81
+ # if not isinstance(packages, dict):
82
+ # raise ValueError(
83
+ # f"Invalid frontend package configuration: {path}"
84
+ # )
85
+
86
+ # for group in ("dependencies", "devDependencies"):
87
+
88
+ # values = packages.get(group, {})
89
+
90
+ # if not isinstance(values, dict):
91
+ # raise ValueError(
92
+ # f"Invalid frontend '{group}' configuration: {path}"
93
+ # )
94
+
95
+ # if not all(
96
+ # isinstance(name, str)
97
+ # and isinstance(version, str)
98
+ # for name, version in values.items()
99
+ # ):
100
+ # raise ValueError(
101
+ # f"Invalid package entries in frontend '{group}': "
102
+ # f"{path}"
103
+ # )
104
+
105
+ # requirements = (
106
+ # backend.get("requirements")
107
+ # if isinstance(backend, dict)
108
+ # else None
109
+ # )
110
+
111
+ # if not isinstance(requirements, list) or not all(
112
+ # isinstance(requirement, str)
113
+ # for requirement in requirements
114
+ # ):
115
+ # raise ValueError(
116
+ # f"Invalid backend requirements configuration: {path}"
117
+ # )
118
+
119
+ # return {
120
+ # "frontend": packages,
121
+ # "backend": requirements,
122
+ # }
123
+
124
+
125
+ def load_dependencies(path: Path) -> dict:
126
+
127
+ if not path.is_file():
128
+ raise FileNotFoundError(
129
+ f"Dependencies configuration not found: {path}"
130
+ )
131
+
132
+ with path.open(
133
+ "r",
134
+ encoding="utf-8",
135
+ ) as file:
136
+ config = json.load(file)
137
+
138
+ if not isinstance(config, dict):
139
+ raise ValueError(
140
+ f"Invalid dependencies configuration: {path}"
141
+ )
142
+
143
+ # ---------------------------------------------------------
144
+ # Validate frontend configuration
145
+ # ---------------------------------------------------------
146
+
147
+ frontend = config.get("frontend")
148
+
149
+ if not isinstance(frontend, dict):
150
+ raise ValueError(
151
+ f"Invalid frontend configuration: {path}"
152
+ )
153
+
154
+ packages = frontend.get("packages")
155
+
156
+ if not isinstance(packages, dict):
157
+ raise ValueError(
158
+ f"Invalid frontend package configuration: {path}"
159
+ )
160
+
161
+ for group in ("dependencies", "devDependencies"):
162
+
163
+ values = packages.get(group, {})
164
+
165
+ if not isinstance(values, dict):
166
+ raise ValueError(
167
+ f"Invalid frontend '{group}' configuration: {path}"
168
+ )
169
+
170
+ if not all(
171
+ isinstance(name, str)
172
+ and name.strip()
173
+ and isinstance(version, str)
174
+ and version.strip()
175
+ for name, version in values.items()
176
+ ):
177
+ raise ValueError(
178
+ f"Invalid package entries in frontend "
179
+ f"'{group}': {path}"
180
+ )
181
+
182
+ # ---------------------------------------------------------
183
+ # Validate backend configuration
184
+ # ---------------------------------------------------------
185
+
186
+ backend = config.get("backend")
187
+
188
+ if not isinstance(backend, dict):
189
+ raise ValueError(
190
+ f"Invalid backend configuration: {path}"
191
+ )
192
+
193
+ requirements = backend.get("requirements")
194
+
195
+ if not isinstance(requirements, dict):
196
+ raise ValueError(
197
+ f"Invalid backend requirements configuration: "
198
+ f"'backend.requirements' must be an object: {path}"
199
+ )
200
+
201
+ if not all(
202
+ isinstance(name, str)
203
+ and name.strip()
204
+ and isinstance(specifier, str)
205
+ and specifier.strip()
206
+ for name, specifier in requirements.items()
207
+ ):
208
+ raise ValueError(
209
+ f"Invalid backend requirements entries: {path}. "
210
+ "Expected package names mapped to non-empty "
211
+ "version specification strings."
212
+ )
213
+
214
+ # ---------------------------------------------------------
215
+ # Return the normalized configuration
216
+ # ---------------------------------------------------------
217
+
218
+ return {
219
+ "frontend": packages,
220
+ "backend": requirements,
221
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "routes": {
3
+ "test": {
4
+ "methods": ["GET"],
5
+ "route": "/test",
6
+ "summary": "Demo test Endpoint",
7
+ "tags": ["test"]
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,35 @@
1
+ import json
2
+ from pathlib import Path
3
+ from fastapi import FastAPI
4
+ # from pydantic import BaseModel
5
+
6
+ app = FastAPI(
7
+ # name="Backend API Docs",
8
+ title="Backend API Docs",
9
+ description="Backend API Docs",
10
+ version="1.0.0",
11
+ # lifespan=lifespan,
12
+ swagger_ui_parameters={
13
+ "docExpansion": "none",
14
+ "displayRequestDuration": True,
15
+ "defaultModelsExpandDepth": -1
16
+ },
17
+ )
18
+
19
+ # dynamically load routes.json to creat
20
+ # endpoints or access using json indexing
21
+ BASE = Path(__file__).resolve().parents[1]
22
+ with open(BASE/"routes.json") as endpoints:
23
+ ROUTES = json.load(endpoints)["routes"]
24
+
25
+ # html response example!
26
+ from fastapi.responses import HTMLResponse
27
+ @app.get(
28
+ ROUTES["test"]["route"],
29
+ summary=ROUTES["test"]["summary"],
30
+ tags=ROUTES["test"]["tags"],
31
+ response_class=HTMLResponse
32
+ )
33
+ def page():
34
+ html = "<h1>FastAPI!</h1>"
35
+ return HTMLResponse(content=html)
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "skeleton-app",
3
+ "version": "1.0.0",
4
+ "description": "skeleton-app",
5
+ "author": "client-author",
6
+ "license": "ISC",
7
+ "main": "dist/index.js",
8
+ "type": "module",
9
+ "devDependencies": {
10
+ "typescript": "^6.0.3",
11
+ "@skeleton/cli": "file:../.skeleton/packages/skeleton-cli-1.0.0.tgz",
12
+ "@skeleton/webpack": "file:../.skeleton/packages/skeleton-webpack-1.0.0.tgz"
13
+ },
14
+ "scripts": {
15
+ "serve": "skeleton serve",
16
+ "build": "skeleton build",
17
+ "preview": "skeleton preview",
18
+ "clean": "skeleton clean",
19
+ "purge": "skeleton purge"
20
+ }
21
+ }