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,84 @@
1
+ from skeleton.infrastructure.runners.src.actions import ACTIONS
2
+
3
+ # command line input may look like:
4
+ # python run.py --start frontend gateway --watch --open
5
+ # python run.py --start --watch --open
6
+
7
+ # arguments are thus:
8
+ # ["--start", "frontend", "gateway", "--watch", "--open"]
9
+
10
+ def parse(argv: list[str]) -> dict:
11
+
12
+ action = "start" # default
13
+
14
+ targets: list[str] = [] # frontend, gateway, packages
15
+
16
+ options: dict[str, str | bool] = {
17
+ "mode": "dev",
18
+ "watch": False,
19
+ "open": False,
20
+ } # dev/prod
21
+
22
+ if argv and argv[0] in ACTIONS:
23
+ action = ACTIONS[argv[0]]
24
+ i = 1
25
+ else:
26
+ i = 0
27
+
28
+ while i < len(argv):
29
+
30
+ arg = argv[i]
31
+
32
+ if arg.startswith("--"):
33
+ break
34
+
35
+ targets.append(arg)
36
+ i += 1
37
+
38
+ while i < len(argv):
39
+
40
+ arg = argv[i]
41
+
42
+ if arg == "--mode":
43
+
44
+ if i + 1 >= len(argv):
45
+ raise ValueError("--mode requires a values to be specified")
46
+
47
+ mode = argv[i + 1]
48
+
49
+ if mode not in ["dev", "prod"]:
50
+ raise ValueError(f"invalid mode: {mode}")
51
+
52
+ options["mode"] = mode
53
+
54
+ i += 2
55
+ continue
56
+
57
+ if arg == "--root":
58
+
59
+ if i + 1 >= len(argv):
60
+ raise ValueError("--root requires a values to be specified")
61
+
62
+ root = argv[i + 1]
63
+ options["root"] = root
64
+
65
+ i += 2
66
+ continue
67
+
68
+ if arg == "--watch":
69
+ options["watch"] = True
70
+ i += 1
71
+ continue
72
+
73
+ if arg == "--open":
74
+ options["open"] = True
75
+ i += 1
76
+ continue
77
+
78
+ raise ValueError(f"Unknown option: {arg}")
79
+
80
+ return {
81
+ "action": action,
82
+ "targets": targets,
83
+ "options": options
84
+ }
@@ -0,0 +1,99 @@
1
+ from subprocess import Popen
2
+
3
+ from skeleton.infrastructure.runners.src.command import Command
4
+
5
+ from skeleton.infrastructure.common.src.context import RuntimeContext
6
+
7
+ from typing import Callable
8
+
9
+ Hook = Callable[["ProcessManager"], None]
10
+
11
+ class ProcessManager:
12
+
13
+ def __init__(self, context: RuntimeContext):
14
+
15
+ self.context = context
16
+
17
+ self.commands: list[Command] = []
18
+ self.processes: list[Popen] = []
19
+
20
+ self.before_start_hooks: list[Hook] = []
21
+ self.after_start_hooks: list[Hook] = []
22
+ self.on_shutdown_hooks: list[Hook] = []
23
+
24
+ def register_hook(
25
+ self, hook: Hook,
26
+ phase: str = "before_start"
27
+ ):
28
+ if phase == "before_start":
29
+ self.before_start_hooks.append(hook)
30
+ elif phase == "after_start":
31
+ self.after_start_hooks.append(hook)
32
+ elif phase == "on_shutdown":
33
+ self.on_shutdown_hooks.append(hook)
34
+
35
+ def register(self, command: Command):
36
+ self.commands.append(command)
37
+
38
+ def spawn(self, command: Command):
39
+ return Popen(
40
+ command.args,
41
+ cwd=command.cwd,
42
+ env=self.context.env,
43
+ shell=False,
44
+ )
45
+
46
+ def start(self):
47
+
48
+ try:
49
+
50
+ # BEFORE START HOOKS
51
+ for hook in self.before_start_hooks:
52
+ hook(self)
53
+
54
+ # spawn processes
55
+ for command in self.commands:
56
+ self.processes.append(
57
+ self.spawn(command)
58
+ )
59
+
60
+ # AFTER START HOOKS
61
+ for hook in self.after_start_hooks:
62
+ hook(self)
63
+
64
+ for p in self.processes:
65
+ p.wait()
66
+
67
+ # fix this issues => twice:
68
+ # Terminate batch job (Y/N)?
69
+ # issue seems to be coming from npm, npx, etc.
70
+ except KeyboardInterrupt:
71
+
72
+ # When ctrl + C for shutdown:
73
+
74
+ # Exception ignored on threading shutdown:
75
+ # Traceback (most recent call last):
76
+
77
+ # File "C:\Users\Lambda\AppData\Local\Programs\Python\Python313\Lib\threading.py", line 1540, in _shutdown
78
+ # _thread_shutdown()
79
+
80
+ print("INFO: shutting down services ...")
81
+
82
+ # ON SHUTDOWN HOOKS!
83
+ for hook in self.on_shutdown_hooks:
84
+ hook(self)
85
+
86
+ for p in self.processes:
87
+ try:
88
+ p.terminate()
89
+ except Exception:
90
+ pass
91
+
92
+ for p in self.processes:
93
+ try:
94
+ p.wait(timeout=3)
95
+ except Exception:
96
+ try:
97
+ p.kill()
98
+ except Exception:
99
+ pass
@@ -0,0 +1,16 @@
1
+ from skeleton.infrastructure.runners.src import (
2
+ packages
3
+ )
4
+ from skeleton.infrastructure.runners.src import frontend, gateway
5
+
6
+ # let tsc handle packages build-order
7
+ SERVICES = {
8
+ "packages": packages,
9
+ "frontend": frontend,
10
+ "gateway": gateway,
11
+ }
12
+
13
+ DEFAULT_TARGETS = [
14
+ "frontend",
15
+ "gateway",
16
+ ]
@@ -0,0 +1,6 @@
1
+ import shutil
2
+
3
+ def resolve_cmd(cmd):
4
+ # npm is npm.cmd on windows!
5
+ # use which to check if npm.cmd
6
+ return shutil.which(cmd) or cmd
@@ -0,0 +1,28 @@
1
+ from skeleton.infrastructure.runners.src.cmd import CMD
2
+ from skeleton.infrastructure.runners.src.actions import ACTIONS
3
+ from skeleton.infrastructure.runners.src.services import SERVICES
4
+
5
+ class CMDValidationError(Exception):
6
+ pass
7
+
8
+ def validate(cmd: CMD):
9
+
10
+ if cmd.action not in ACTIONS.values():
11
+ raise CMDValidationError(
12
+ f"Unknown action: {cmd.action}"
13
+ )
14
+
15
+ for target in cmd.targets:
16
+
17
+ if target not in SERVICES:
18
+ raise CMDValidationError(
19
+ f"Unknown service: {target}"
20
+ )
21
+
22
+ service = SERVICES[target]
23
+
24
+ if not hasattr(service, cmd.action):
25
+ raise CMDValidationError(
26
+ f"Service {service}" f" "
27
+ f"does not have action {cmd.action}"
28
+ )
skeleton/root.py ADDED
@@ -0,0 +1,234 @@
1
+ import shutil
2
+
3
+ from pathlib import Path
4
+
5
+ def _remove_path(
6
+ path: Path,
7
+ ) -> None:
8
+
9
+ if path.is_dir() and not path.is_symlink():
10
+
11
+ shutil.rmtree(path)
12
+
13
+ print(f"Removed directory: {path}")
14
+
15
+ elif path.is_file() or path.is_symlink():
16
+
17
+ path.unlink()
18
+
19
+ print(f"Removed file: {path}")
20
+
21
+ def clean_framework(
22
+ framework_root: Path,
23
+ ) -> int:
24
+
25
+ framework_root = framework_root.resolve()
26
+
27
+ # Remove generated Python distribution artifacts and
28
+ # JavaScript/TypeScript package build outputs.
29
+ #
30
+ # Keep node_modules, lockfiles, the development virtual
31
+ # environment, and packaged framework tarballs intact.
32
+
33
+ targets = [
34
+ framework_root / "dist",
35
+ framework_root / "skeleton_framework.egg-info",
36
+ framework_root / ".mypy_cache",
37
+ framework_root / "skeleton" / "packages" / "cli" / "dist",
38
+ framework_root / "skeleton" / "packages" / "webpack" / "dist",
39
+ ]
40
+
41
+ for target in targets:
42
+
43
+ _remove_path(target)
44
+
45
+ # Remove TypeScript build information from the framework's
46
+ # own package sources without traversing node_modules.
47
+
48
+ package_directories = [
49
+ framework_root / "skeleton" / "packages" / "cli",
50
+ framework_root / "skeleton" / "packages" / "webpack",
51
+ ]
52
+
53
+ for directory in package_directories:
54
+
55
+ if not directory.is_dir():
56
+ continue
57
+
58
+ for target in directory.glob("*.tsbuildinfo"):
59
+
60
+ _remove_path(target)
61
+
62
+ print("Framework clean completed.")
63
+
64
+ return 0
65
+
66
+ def purge_framework(
67
+ framework_root: Path,
68
+ ) -> int:
69
+
70
+ framework_root = framework_root.resolve()
71
+
72
+ # Purge includes clean, plus installed development
73
+ # dependencies, lockfiles, and packaged client tarballs.
74
+ #
75
+ # The framework's Python virtual environment is preserved.
76
+
77
+ clean_framework(framework_root)
78
+
79
+ targets = [
80
+ framework_root / "node_modules",
81
+ framework_root / "skeleton" / "packages" / "cli" / "node_modules",
82
+ framework_root / "skeleton" / "packages" / "webpack" / "node_modules",
83
+ framework_root / "package-lock.json",
84
+ framework_root / "skeleton" / "packages" / "cli" / "package-lock.json",
85
+ framework_root / "skeleton" / "packages" / "webpack" / "package-lock.json",
86
+ framework_root / "skeleton" / "packages" / ".skeleton",
87
+ ]
88
+
89
+ for target in targets:
90
+
91
+ _remove_path(target)
92
+
93
+ print("Framework purge completed.")
94
+
95
+ return 0
96
+
97
+ def main(
98
+ argv: list[str] | None = None,
99
+ framework_root: Path | None = None,
100
+ project_root: Path | None = None,
101
+ ) -> int:
102
+
103
+ import sys
104
+
105
+ args = sys.argv[1:] if argv is None else argv
106
+
107
+ if framework_root is None:
108
+
109
+ framework_root = Path(__file__).resolve().parent.parent
110
+
111
+ framework_root = framework_root.resolve()
112
+
113
+ if project_root is None:
114
+
115
+ project_root = Path.cwd().resolve()
116
+
117
+ project_root = project_root.resolve()
118
+
119
+ from skeleton.cli import is_framework_repository
120
+
121
+ if not is_framework_repository(framework_root):
122
+
123
+ print(
124
+ "Error: Framework development commands require "
125
+ "the Skeleton framework source repository."
126
+ )
127
+
128
+ return 2
129
+
130
+ if not args:
131
+
132
+ print(
133
+ "Usage: python run.py "
134
+ "--bootstrap | --dist | --init | --install | "
135
+ "--pack | --build | --clean | --purge"
136
+ )
137
+
138
+ return 0
139
+
140
+ command = args[0]
141
+
142
+ if command == "--bootstrap":
143
+
144
+ from skeleton.infrastructure.bootstrap.src.commands.dev.init import (
145
+ dev_init,
146
+ )
147
+
148
+ from skeleton.infrastructure.bootstrap.src.commands.dev.install import (
149
+ dev_install,
150
+ )
151
+
152
+ print("\n[1/2] Initializing framework development...\n")
153
+
154
+ dev_init(framework_root)
155
+
156
+ print("\n[2/2] Installing framework development dependencies...\n")
157
+
158
+ dev_install(framework_root)
159
+
160
+ print("\nFramework bootstrap completed successfully.")
161
+
162
+ return 0
163
+
164
+ if command == "--dist":
165
+
166
+ from skeleton.infrastructure.bootstrap.src.commands.dev.pack import (
167
+ dev_pack,
168
+ )
169
+
170
+ from skeleton.infrastructure.bootstrap.src.commands.dev.build import (
171
+ dev_build,
172
+ )
173
+
174
+ print("\n[1/2] Packaging framework dependencies...\n")
175
+
176
+ dev_pack(framework_root)
177
+
178
+ print("\n[2/2] Building framework distribution...\n")
179
+
180
+ dev_build(framework_root)
181
+
182
+ print("\nFramework distribution completed successfully.")
183
+
184
+ return 0
185
+
186
+ if command == "--init":
187
+
188
+ from skeleton.infrastructure.bootstrap.src.commands.dev.init import (
189
+ dev_init,
190
+ )
191
+
192
+ dev_init(framework_root)
193
+
194
+ return 0
195
+
196
+ if command == "--install":
197
+
198
+ from skeleton.infrastructure.bootstrap.src.commands.dev.install import (
199
+ dev_install,
200
+ )
201
+
202
+ dev_install(framework_root)
203
+
204
+ return 0
205
+
206
+ if command == "--pack":
207
+
208
+ from skeleton.infrastructure.bootstrap.src.commands.dev.pack import (
209
+ dev_pack,
210
+ )
211
+
212
+ dev_pack(framework_root)
213
+
214
+ return 0
215
+
216
+ if command == "--build":
217
+
218
+ from skeleton.infrastructure.bootstrap.src.commands.dev.build import (
219
+ dev_build,
220
+ )
221
+
222
+ dev_build(framework_root)
223
+
224
+ return 0
225
+
226
+ if command == "--clean":
227
+
228
+ return clean_framework(framework_root)
229
+
230
+ if command == "--purge":
231
+
232
+ return purge_framework(framework_root)
233
+
234
+ raise ValueError(f"Unknown framework command: {command}")