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
skeleton/__init__.py ADDED
File without changes
skeleton/cli.py ADDED
@@ -0,0 +1,151 @@
1
+ import sys
2
+
3
+ from pathlib import Path
4
+
5
+ # ============================================================
6
+ # Framework commands (run from the framework root)
7
+ # ============================================================
8
+
9
+ # python run.py --bootstrap
10
+ # python run.py --dist
11
+
12
+ # python run.py --init
13
+ # python run.py --install
14
+ # python run.py --pack
15
+ # python run.py --build
16
+
17
+ # python run.py --clean
18
+ # python run.py --purge
19
+
20
+ # python path/to/run.py --config
21
+ # python path/to/run.py --init
22
+ # python path/to/run.py --install
23
+ # python path/to/run.py --start frontend gateway packages --open
24
+
25
+ # ============================================================
26
+ # Client commands (run from a client project root)
27
+ # ============================================================
28
+
29
+ # skeleton --config
30
+ # skeleton --init
31
+ # skeleton --install
32
+ # skeleton --start
33
+ # skeleton --start frontend gateway --open
34
+ # skeleton --quickstart
35
+
36
+ # skeleton --serve
37
+ # skeleton --build
38
+ # skeleton --preview
39
+ # skeleton --clean
40
+ # skeleton --purge
41
+
42
+ def is_framework_repository(
43
+ path: Path,
44
+ ) -> bool:
45
+
46
+ path = path.resolve()
47
+
48
+ return (
49
+ (path / "run.py").is_file()
50
+ and (path / "pyproject.toml").is_file()
51
+ and (path / "skeleton" / "infrastructure").is_dir()
52
+ and (path / "skeleton" / "packages").is_dir()
53
+ )
54
+
55
+ def main(
56
+ argv: list[str] | None = None,
57
+ framework_root: Path | None = None,
58
+ ) -> int:
59
+
60
+ args = sys.argv[1:] if argv is None else argv
61
+
62
+ # When installed through PyPI, skeleton/cli.py lives inside
63
+ # site-packages/skeleton/. Its parent directory is site-packages.
64
+ #
65
+ # In the source repository,
66
+ # its parent directory is the
67
+ # framework repository root.
68
+
69
+ if framework_root is None:
70
+
71
+ framework_root = Path(__file__).resolve().parent.parent
72
+
73
+ framework_root = framework_root.resolve()
74
+ project_root = Path.cwd().resolve()
75
+
76
+ # Framework commands and client commands share some names.
77
+ #
78
+ # When running from the actual framework source repository,
79
+ # dispatch to root.py.
80
+ #
81
+ # Otherwise, dispatch client commands to client.py.
82
+
83
+ is_framework_root = is_framework_repository(project_root)
84
+
85
+ if not args:
86
+
87
+ print(
88
+ "Usage: skeleton "
89
+ "--config | --init | --install | --start | --quickstart"
90
+ )
91
+
92
+ return 0
93
+
94
+ command = args[0]
95
+
96
+ # These commands only operate on the framework source repository.
97
+ # Route them to root.py regardless of the current directory so
98
+ # root.py can report a clear error if necessary.
99
+
100
+ root_only_commands = {
101
+ "--bootstrap",
102
+ "--dist",
103
+ "--pack",
104
+ }
105
+
106
+ # Shared command names are interpreted according to the
107
+ # current working directory.
108
+
109
+ root_or_client_commands = {
110
+ "--init",
111
+ "--install",
112
+ "--build",
113
+ "--clean",
114
+ "--purge",
115
+ }
116
+
117
+ if command in root_only_commands:
118
+
119
+ from skeleton.root import main as root_main
120
+
121
+ return root_main(
122
+ argv=args,
123
+ framework_root=(
124
+ project_root
125
+ if is_framework_root
126
+ else framework_root
127
+ ),
128
+ project_root=project_root,
129
+ )
130
+
131
+ if command in root_or_client_commands and is_framework_root:
132
+
133
+ from skeleton.root import main as root_main
134
+
135
+ return root_main(
136
+ argv=args,
137
+ framework_root=project_root,
138
+ project_root=project_root,
139
+ )
140
+
141
+ from skeleton.client import main as client_main
142
+
143
+ return client_main(
144
+ argv=args,
145
+ framework_root=framework_root,
146
+ project_root=project_root,
147
+ )
148
+
149
+
150
+ if __name__ == "__main__":
151
+ raise SystemExit(main())
skeleton/client.py ADDED
@@ -0,0 +1,269 @@
1
+
2
+ import json
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+
7
+ from pathlib import Path
8
+
9
+ FRONTEND_SCRIPTS = {
10
+ "--serve": "serve",
11
+ "--build": "build",
12
+ "--preview": "preview",
13
+ "--clean": "clean",
14
+ "--purge": "purge",
15
+ }
16
+
17
+ def run_frontend_script(
18
+ command: str,
19
+ project_root: Path,
20
+ ) -> int:
21
+
22
+ if command not in FRONTEND_SCRIPTS:
23
+ print(f"Error: Unsupported frontend command: {command}")
24
+ return 2
25
+
26
+ project_root = project_root.resolve()
27
+
28
+ # Read the client's generated configuration.
29
+ # Do not read the framework's templates directory here.
30
+
31
+ layout_path = project_root / "skeleton-layout.json"
32
+
33
+ if not layout_path.is_file():
34
+ print(
35
+ "Error: Skeleton project layout not found: "
36
+ f"{layout_path}"
37
+ )
38
+ return 1
39
+
40
+ try:
41
+ with layout_path.open("r", encoding="utf-8") as file:
42
+ layout = json.load(file)
43
+
44
+ except (OSError, json.JSONDecodeError) as error:
45
+ print(f"Error reading Skeleton project layout: {error}")
46
+ return 1
47
+
48
+ if not isinstance(layout, dict):
49
+ print(
50
+ "Error: Skeleton project layout must contain "
51
+ "a JSON object."
52
+ )
53
+ return 1
54
+
55
+ frontend_config = layout.get("frontend")
56
+
57
+ if not isinstance(frontend_config, dict):
58
+ print(
59
+ "Error: 'frontend' must be an object in "
60
+ "skeleton-layout.json."
61
+ )
62
+ return 1
63
+
64
+ frontend_name = frontend_config.get("directory")
65
+
66
+ if (
67
+ not isinstance(frontend_name, str)
68
+ or not frontend_name.strip()
69
+ or Path(frontend_name).is_absolute()
70
+ or len(Path(frontend_name).parts) != 1
71
+ or frontend_name in (".", "..")
72
+ ):
73
+ print(
74
+ "Error: 'frontend.directory' must be a single "
75
+ "relative directory name in skeleton-layout.json."
76
+ )
77
+ return 1
78
+
79
+ frontend_root = project_root / frontend_name
80
+ package_json = frontend_root / "package.json"
81
+
82
+ if not package_json.is_file():
83
+ print(
84
+ "Error: Frontend package manifest not found: "
85
+ f"{package_json}"
86
+ )
87
+ return 1
88
+
89
+ try:
90
+ with package_json.open("r", encoding="utf-8") as file:
91
+ package = json.load(file)
92
+
93
+ except (OSError, json.JSONDecodeError) as error:
94
+ print(f"Error reading frontend package.json: {error}")
95
+ return 1
96
+
97
+ if not isinstance(package, dict):
98
+ print(
99
+ "Error: Frontend package manifest must contain "
100
+ f"a JSON object: {package_json}"
101
+ )
102
+ return 1
103
+
104
+ script_name = FRONTEND_SCRIPTS[command]
105
+ scripts = package.get("scripts", {})
106
+
107
+ if not isinstance(scripts, dict) or script_name not in scripts:
108
+ print(
109
+ f"Error: Frontend script {script_name!r} "
110
+ f"is not defined in {package_json}."
111
+ )
112
+ return 1
113
+
114
+ npm = shutil.which("npm")
115
+
116
+ if npm is None:
117
+ print("Error: npm was not found. Install Node.js and npm.")
118
+ return 1
119
+
120
+ print(
121
+ f"INFO: Running frontend script '{script_name}' "
122
+ f"in {frontend_root}"
123
+ )
124
+
125
+ try:
126
+ if os.name == "nt":
127
+ # npm is commonly exposed as npm.cmd on Windows.
128
+ command_line = subprocess.list2cmdline(
129
+ [npm, "run", script_name]
130
+ )
131
+
132
+ result = subprocess.run(
133
+ command_line,
134
+ cwd=frontend_root,
135
+ shell=True,
136
+ check=False,
137
+ )
138
+
139
+ else:
140
+ result = subprocess.run(
141
+ [npm, "run", script_name],
142
+ cwd=frontend_root,
143
+ check=False,
144
+ )
145
+
146
+ return result.returncode
147
+
148
+ except OSError as error:
149
+ print(f"Error running frontend script: {error}")
150
+ return 1
151
+
152
+
153
+ def main(
154
+ argv: list[str],
155
+ framework_root: Path,
156
+ project_root: Path,
157
+ ) -> int:
158
+
159
+ args = argv
160
+
161
+ framework_root = framework_root.resolve()
162
+ project_root = project_root.resolve()
163
+
164
+ if not args:
165
+ print(
166
+ "Usage: skeleton "
167
+ "--config | --init | --install | --start | "
168
+ "--serve | --build | --preview | --clean | "
169
+ "--purge | --quickstart | --quick-start"
170
+ )
171
+ return 0
172
+
173
+ command = args[0]
174
+
175
+ if command == "--config":
176
+
177
+ from skeleton.infrastructure.bootstrap.src.config import config
178
+
179
+ config(
180
+ framework_root=framework_root,
181
+ project_root=project_root,
182
+ )
183
+
184
+ return 0
185
+
186
+ if command == "--init":
187
+
188
+ from skeleton.infrastructure.bootstrap.src.commands.client.init import (
189
+ init,
190
+ )
191
+
192
+ init(
193
+ framework_root=framework_root,
194
+ project_root=project_root,
195
+ )
196
+
197
+ return 0
198
+
199
+ if command == "--install":
200
+
201
+ from skeleton.infrastructure.bootstrap.src.commands.client.install import (
202
+ install,
203
+ )
204
+
205
+ install(
206
+ framework_root=framework_root,
207
+ project_root=project_root,
208
+ )
209
+
210
+ return 0
211
+
212
+ if command == "--start":
213
+
214
+ from skeleton.infrastructure.runners.src.main import run
215
+
216
+ run(
217
+ framework_root=framework_root,
218
+ project_root=project_root,
219
+ argv=args,
220
+ )
221
+
222
+ return 0
223
+
224
+ if command in FRONTEND_SCRIPTS:
225
+
226
+ return run_frontend_script(
227
+ command=command,
228
+ project_root=project_root,
229
+ )
230
+
231
+ if command in ("--quickstart", "--quick-start"):
232
+
233
+ from skeleton.infrastructure.bootstrap.src.config import config
234
+
235
+ from skeleton.infrastructure.bootstrap.src.commands.client.init import (
236
+ init,
237
+ )
238
+
239
+ from skeleton.infrastructure.bootstrap.src.commands.client.install import (
240
+ install,
241
+ )
242
+
243
+ print("\n[1/3] Generating project configuration...\n")
244
+
245
+ config(
246
+ framework_root=framework_root,
247
+ project_root=project_root,
248
+ )
249
+
250
+ print("\n[2/3] Initializing project...\n")
251
+
252
+ init(
253
+ framework_root=framework_root,
254
+ project_root=project_root,
255
+ )
256
+
257
+ print("\n[3/3] Installing project dependencies...\n")
258
+
259
+ install(
260
+ framework_root=framework_root,
261
+ project_root=project_root,
262
+ )
263
+
264
+ print("\nQuickstart completed successfully.")
265
+ print("Run 'skeleton --start' to start your project.")
266
+
267
+ return 0
268
+
269
+ raise ValueError(f"Unknown client command: {command}")
@@ -0,0 +1 @@
1
+ from skeleton.infrastructure.runners.src import main
File without changes
File without changes