create-star-app 1.0.0__tar.gz

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 (30) hide show
  1. create_star_app-1.0.0/LICENSE +21 -0
  2. create_star_app-1.0.0/PKG-INFO +67 -0
  3. create_star_app-1.0.0/README.md +43 -0
  4. create_star_app-1.0.0/create_star_app/__init__.py +0 -0
  5. create_star_app-1.0.0/create_star_app/cli.py +59 -0
  6. create_star_app-1.0.0/create_star_app/config.py +15 -0
  7. create_star_app-1.0.0/create_star_app/scaffold.py +62 -0
  8. create_star_app-1.0.0/create_star_app/templates/ApiRequests.py.tmpl +90 -0
  9. create_star_app-1.0.0/create_star_app/templates/AppConfig.py.tmpl +116 -0
  10. create_star_app-1.0.0/create_star_app/templates/AppCreator.py.tmpl +588 -0
  11. create_star_app-1.0.0/create_star_app/templates/AuthHandler.py.tmpl +17 -0
  12. create_star_app-1.0.0/create_star_app/templates/PubSubRequests.py.tmpl +6 -0
  13. create_star_app-1.0.0/create_star_app/templates/conftest.py.tmpl +9 -0
  14. create_star_app-1.0.0/create_star_app/templates/mongoDb.py.tmpl +489 -0
  15. create_star_app-1.0.0/create_star_app/templates/objects.py.tmpl +76 -0
  16. create_star_app-1.0.0/create_star_app/templates/pubSub.py.tmpl +589 -0
  17. create_star_app-1.0.0/create_star_app/templates/pubSubAdmin.py.tmpl +533 -0
  18. create_star_app-1.0.0/create_star_app/templates/pytest.ini.tmpl +5 -0
  19. create_star_app-1.0.0/create_star_app/templates/requirements.txt.tmpl +11 -0
  20. create_star_app-1.0.0/create_star_app/templates/roles.py.tmpl +170 -0
  21. create_star_app-1.0.0/create_star_app/templates/route_config.py.tmpl +76 -0
  22. create_star_app-1.0.0/create_star_app/templates/utils.py.tmpl +114 -0
  23. create_star_app-1.0.0/create_star_app.egg-info/PKG-INFO +67 -0
  24. create_star_app-1.0.0/create_star_app.egg-info/SOURCES.txt +28 -0
  25. create_star_app-1.0.0/create_star_app.egg-info/dependency_links.txt +1 -0
  26. create_star_app-1.0.0/create_star_app.egg-info/entry_points.txt +2 -0
  27. create_star_app-1.0.0/create_star_app.egg-info/top_level.txt +1 -0
  28. create_star_app-1.0.0/pyproject.toml +41 -0
  29. create_star_app-1.0.0/setup.cfg +4 -0
  30. create_star_app-1.0.0/setup.py +5 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adrian Anton Ladia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.1
2
+ Name: create-star-app
3
+ Version: 1.0.0
4
+ Summary: Flask architecture scaffolding tool — generates core server files for the star app architecture.
5
+ Author-email: "Adrian Anton D. Ladia" <ladiaadrian@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/AALadia/create-star-app
8
+ Project-URL: Repository, https://github.com/AALadia/create-star-app
9
+ Project-URL: Issues, https://github.com/AALadia/create-star-app/issues
10
+ Keywords: flask,scaffolding,boilerplate,code-generator
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Framework :: Flask
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Code Generators
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+
25
+ # create-star-app
26
+
27
+ Flask architecture scaffolding tool that generates core server files for the star app architecture.
28
+
29
+ ## What it does
30
+
31
+ `create-star-app` is an interactive CLI that prompts for project configuration (name, port, timezone, etc.) and generates a ready-to-use Flask server directory with all the boilerplate files pre-configured.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install -e .
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ Run the CLI from the directory where you want to create your project:
42
+
43
+ ```bash
44
+ create-star-app
45
+ ```
46
+
47
+ You will be prompted for:
48
+
49
+ - **Project name** (required)
50
+ - **Port** (default: 5000)
51
+ - **Production server endpoint** (default: empty)
52
+ - **Client app subdirectory** (default: client/src/app)
53
+ - **Timezone offset** (default: 8)
54
+
55
+ The tool will generate the `server/`, `server/schemas/`, and `.vscode/` directories with all template files rendered using your configuration.
56
+
57
+ ## Development
58
+
59
+ ```bash
60
+ pip install -e .
61
+ ```
62
+
63
+ Then run directly:
64
+
65
+ ```bash
66
+ python -m create_star_app.cli
67
+ ```
@@ -0,0 +1,43 @@
1
+ # create-star-app
2
+
3
+ Flask architecture scaffolding tool that generates core server files for the star app architecture.
4
+
5
+ ## What it does
6
+
7
+ `create-star-app` is an interactive CLI that prompts for project configuration (name, port, timezone, etc.) and generates a ready-to-use Flask server directory with all the boilerplate files pre-configured.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install -e .
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ Run the CLI from the directory where you want to create your project:
18
+
19
+ ```bash
20
+ create-star-app
21
+ ```
22
+
23
+ You will be prompted for:
24
+
25
+ - **Project name** (required)
26
+ - **Port** (default: 5000)
27
+ - **Production server endpoint** (default: empty)
28
+ - **Client app subdirectory** (default: client/src/app)
29
+ - **Timezone offset** (default: 8)
30
+
31
+ The tool will generate the `server/`, `server/schemas/`, and `.vscode/` directories with all template files rendered using your configuration.
32
+
33
+ ## Development
34
+
35
+ ```bash
36
+ pip install -e .
37
+ ```
38
+
39
+ Then run directly:
40
+
41
+ ```bash
42
+ python -m create_star_app.cli
43
+ ```
File without changes
@@ -0,0 +1,59 @@
1
+ from create_star_app.config import ProjectConfig
2
+ from create_star_app import scaffold
3
+
4
+
5
+ def _prompt(label: str, default: str = "") -> str:
6
+ """Prompt the user for input, showing a default value if provided."""
7
+ if default:
8
+ raw = input(f" {label} [{default}]: ").strip()
9
+ return raw if raw else default
10
+ else:
11
+ return input(f" {label}: ").strip()
12
+
13
+
14
+ def main() -> None:
15
+ print()
16
+ print("=" * 56)
17
+ print(" create-star-app")
18
+ print(" Flask Architecture Scaffolding Tool")
19
+ print("=" * 56)
20
+ print()
21
+
22
+ # projectName is required — loop until non-empty
23
+ project_name = ""
24
+ while not project_name:
25
+ project_name = _prompt("Project name (required)")
26
+ if not project_name:
27
+ print(" Project name cannot be empty. Please try again.")
28
+
29
+ port_str = _prompt("Port", "5000")
30
+ try:
31
+ port = int(port_str)
32
+ except ValueError:
33
+ print(f" Invalid port '{port_str}', using default 5000.")
34
+ port = 5000
35
+
36
+ production_endpoint = _prompt("Production server endpoint", "")
37
+ client_subdir = _prompt("Client app subdirectory", "client/src/app")
38
+
39
+ tz_str = _prompt("Timezone offset (hours)", "8")
40
+ try:
41
+ timezone = int(tz_str)
42
+ except ValueError:
43
+ print(f" Invalid timezone '{tz_str}', using default 8.")
44
+ timezone = 8
45
+
46
+ config = ProjectConfig(
47
+ projectName=project_name,
48
+ port=port,
49
+ productionServerEndpoint=production_endpoint,
50
+ clientAppSubdir=client_subdir,
51
+ timezone=timezone,
52
+ )
53
+
54
+ print()
55
+ scaffold.create_project(config)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ main()
@@ -0,0 +1,15 @@
1
+ from dataclasses import dataclass, asdict
2
+
3
+
4
+ @dataclass
5
+ class ProjectConfig:
6
+ projectName: str
7
+ port: int = 5000
8
+ productionServerEndpoint: str = ""
9
+ clientAppSubdir: str = "client/src/app"
10
+ timezone: int = 8
11
+ ensureIndexesBody: str = "pass"
12
+
13
+ def to_template_vars(self) -> dict:
14
+ """Return a flat dict of all values for string.Template substitution."""
15
+ return asdict(self)
@@ -0,0 +1,62 @@
1
+ from pathlib import Path
2
+ from string import Template
3
+
4
+ from create_star_app.config import ProjectConfig
5
+
6
+ # Locate the templates directory shipped with this package.
7
+ _TEMPLATES_DIR = Path(__file__).resolve().parent / "templates"
8
+
9
+ # Files that live outside the server/ directory.
10
+ _ROOT_TARGETS = {
11
+ "requirements.txt.tmpl": "server/requirements.txt",
12
+ "pytest.ini.tmpl": "server/pytest.ini",
13
+ }
14
+
15
+
16
+ def create_project(config: ProjectConfig) -> None:
17
+ """Scaffold a new project from templates using the given config."""
18
+ base = Path.cwd()
19
+ template_vars = config.to_template_vars()
20
+
21
+ # Create target directories.
22
+ dirs = [
23
+ base / "server",
24
+ base / "server" / "schemas",
25
+ base / ".vscode",
26
+ ]
27
+ for d in dirs:
28
+ d.mkdir(parents=True, exist_ok=True)
29
+ print(f" [dir] {d.relative_to(base)}/")
30
+
31
+ # Process every .tmpl file found in the templates directory.
32
+ tmpl_files = sorted(_TEMPLATES_DIR.glob("*.tmpl"))
33
+ if not tmpl_files:
34
+ print(" Warning: no .tmpl files found in templates directory.")
35
+ return
36
+
37
+ for tmpl_path in tmpl_files:
38
+ tmpl_name = tmpl_path.name # e.g. "app.py.tmpl"
39
+ output_name = tmpl_name.removesuffix(".tmpl") # e.g. "app.py"
40
+
41
+ # Determine the output path.
42
+ if tmpl_name in _ROOT_TARGETS:
43
+ rel = Path(_ROOT_TARGETS[tmpl_name])
44
+ else:
45
+ rel = Path("server") / output_name
46
+
47
+ dest = base / rel
48
+ dest.parent.mkdir(parents=True, exist_ok=True)
49
+
50
+ # Read, substitute, write.
51
+ raw = tmpl_path.read_text(encoding="utf-8")
52
+ rendered = Template(raw).safe_substitute(template_vars)
53
+ dest.write_text(rendered, encoding="utf-8")
54
+
55
+ print(f" [file] {rel}")
56
+
57
+ print()
58
+ print("Project scaffolded successfully! Next steps:")
59
+ print(f" 1. cd {config.projectName}")
60
+ print(" 2. pip install -r server/requirements.txt")
61
+ print(" 3. python server/app.py")
62
+ print()
@@ -0,0 +1,90 @@
1
+ from route_config import route_config
2
+ from objects import User
3
+ from mongoDb import db
4
+ from typing import List
5
+ from utils import generateRandomString
6
+ import datetime
7
+ from roles import Role, AllRoles, UserRoleTypes
8
+
9
+
10
+ class AuthActions():
11
+
12
+ @route_config(httpMethod='POST',
13
+ jwtRequired=False,
14
+ createAccessToken=True,
15
+ successMessage='Login successful')
16
+ def loginWithGoogle(self, firebaseUserObject: dict) -> User:
17
+ from AuthHandler import FirebaseUserObject
18
+ from functions import getOrCreateUser
19
+ firebaseUser = FirebaseUserObject(**firebaseUserObject)
20
+ user = getOrCreateUser(email=firebaseUser.email,
21
+ name=firebaseUser.displayName)
22
+ return user
23
+
24
+ @route_config(httpMethod='POST',
25
+ jwtRequired=False,
26
+ successMessage='Dev user list fetched successfully')
27
+ def devGetUserList(self) -> list:
28
+ from AppConfig import Environment
29
+ if not Environment().getIsDevEnvironment():
30
+ raise PermissionError(
31
+ 'This endpoint is only available in dev environments')
32
+ users = db.read({},
33
+ 'Users',
34
+ projection={
35
+ '_id': 1,
36
+ 'name': 1,
37
+ 'userType': 1
38
+ })
39
+ return users
40
+
41
+ @route_config(httpMethod='POST',
42
+ jwtRequired=False,
43
+ createAccessToken=True,
44
+ successMessage='Dev login successful')
45
+ def devLogin(self, userId: str) -> dict:
46
+ from AppConfig import Environment
47
+ if not Environment().getIsDevEnvironment():
48
+ raise PermissionError(
49
+ 'This endpoint is only available in dev environments')
50
+ user = db.read({'_id': userId}, 'Users', findOne=True)
51
+ if not user:
52
+ raise ValueError(f'User {userId} not found')
53
+ return user
54
+
55
+
56
+ class RolesActions():
57
+
58
+ @route_config(httpMethod='POST',
59
+ jwtRequired=True,
60
+ successMessage='Roles fetched successfully',
61
+ roleAccess='canUpdateUserRole')
62
+ def getRoles(self, userId: str) -> List[Role]:
63
+ allRoles = AllRoles()
64
+ return [x.model_dump(by_alias=True) for x in allRoles.getAllRoles()]
65
+
66
+ @route_config(httpMethod='POST',
67
+ jwtRequired=True,
68
+ successMessage='User role types fetched successfully',
69
+ roleAccess='canUpdateUserRole')
70
+ def getUserRoleTypes(self, userId: str) -> dict:
71
+ roleTypes = UserRoleTypes()
72
+ result = {}
73
+ for userType in roleTypes.getUserTypes():
74
+ result[userType] = roleTypes.getConfig(userType)
75
+ allRoleIds = AllRoles().getAllRoleIds()
76
+ result['superAdmin'] = {
77
+ roleId: (True if roleId != 'canUpdateUserRole' else False)
78
+ for roleId in allRoleIds
79
+ }
80
+ return result
81
+
82
+
83
+ # Add your project-specific action classes below
84
+
85
+
86
+ class ApiRequests(AuthActions, RolesActions):
87
+
88
+ def __init__(self):
89
+ AuthActions.__init__(self)
90
+ RolesActions.__init__(self)
@@ -0,0 +1,116 @@
1
+ import os
2
+ import datetime
3
+
4
+ if os.getenv('ENVIRONMENT', '').startswith('local'):
5
+ from dotenv import load_dotenv
6
+ load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), '.env'))
7
+
8
+
9
+ class Project:
10
+
11
+ def __init__(self):
12
+ self.projectName = '$projectName'
13
+ self.projectId = os.getenv('GOOGLE_CLOUD_PROJECT_ID')
14
+
15
+
16
+ class PubSubConfig:
17
+ def __init__(self):
18
+ import re
19
+ import importlib.util
20
+ from services.__abstractService import AbstractService
21
+
22
+ services_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'services')
23
+ self._serviceEnabled = {}
24
+ for filename in os.listdir(services_dir):
25
+ if not filename.endswith('.py'):
26
+ continue
27
+ module_name = filename[:-3]
28
+ filepath = os.path.join(services_dir, filename)
29
+ try:
30
+ spec = importlib.util.spec_from_file_location(module_name, filepath)
31
+ module = importlib.util.module_from_spec(spec)
32
+ spec.loader.exec_module(module)
33
+ except Exception:
34
+ continue
35
+ for var_name, obj in vars(module).items():
36
+ if isinstance(obj, AbstractService):
37
+ service_name = var_name
38
+ env_var_name = 'PUBSUB_ENABLED_' + re.sub(r'(?<=[a-z0-9])([A-Z])', r'_\1', service_name).upper()
39
+ value = os.getenv(env_var_name)
40
+ if value is None:
41
+ raise Exception(f"{env_var_name} environment variable is not set")
42
+ value = value.lower()
43
+ if value not in ['true', 'false']:
44
+ raise Exception(f"Invalid {env_var_name} environment variable")
45
+ self._serviceEnabled[service_name] = value == 'true'
46
+
47
+ def isServiceEnabled(self, serviceName: str) -> bool:
48
+ if serviceName not in self._serviceEnabled:
49
+ raise ValueError(f"Unknown service: {serviceName}. Available: {list(self._serviceEnabled.keys())}")
50
+ return self._serviceEnabled[serviceName]
51
+
52
+
53
+ class MongoDb(Project):
54
+
55
+ def __init__(self):
56
+ super().__init__()
57
+ self.databaseName = os.getenv('databaseName') if os.getenv(
58
+ 'databaseName') else 'test' + self.projectName
59
+
60
+ def getDatabaseName(self):
61
+ return self.databaseName
62
+
63
+ def getUseReplicaSet(self):
64
+ return self.useReplicaSet
65
+
66
+
67
+ class Timezone:
68
+
69
+ def __init__(self):
70
+ super().__init__()
71
+ self.timezone = $timezone
72
+
73
+ def getTimezone(self):
74
+ return datetime.timezone(datetime.timedelta(hours=self.timezone))
75
+
76
+
77
+ class Environment:
78
+
79
+ def __init__(self):
80
+ super().__init__()
81
+ self.environment = os.getenv('ENVIRONMENT')
82
+ if self.environment not in [
83
+ 'localdev', 'localprod', 'clouddev', 'cloudprod'
84
+ ]:
85
+ raise Exception("Invalid environment")
86
+
87
+ def getEnvironment(self):
88
+ return self.environment
89
+
90
+ def getIsCloudEnvironment(self):
91
+ return self.getEnvironment() in ['clouddev', 'cloudprod']
92
+
93
+ def getIsProductionEnvironment(self):
94
+ return self.getEnvironment() in ['cloudprod']
95
+
96
+ def getisLocalDevEnvironment(self):
97
+ return self.getEnvironment() in ['localdev']
98
+
99
+ def getisLocalEnvironment(self):
100
+ return self.getEnvironment() in ['localdev', 'localprod']
101
+
102
+ def getIsDevEnvironment(self):
103
+ return self.getEnvironment() in ['localdev', 'clouddev']
104
+
105
+
106
+ class AppConfig(Environment, PubSubConfig, Timezone, MongoDb):
107
+
108
+ def __init__(self):
109
+ Environment.__init__(self)
110
+ PubSubConfig.__init__(self)
111
+ Timezone.__init__(self)
112
+ MongoDb.__init__(self)
113
+
114
+
115
+ if __name__ == "__main__":
116
+ appConfig = AppConfig()