quickscale-cli 0.61.0__tar.gz → 0.63.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.
- quickscale_cli-0.63.0/PKG-INFO +24 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/pyproject.toml +5 -4
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/_version.py +1 -1
- quickscale_cli-0.63.0/src/quickscale_cli/commands/module_commands.py +457 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/main.py +8 -2
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/utils/railway_utils.py +35 -10
- quickscale_cli-0.61.0/PKG-INFO +0 -206
- quickscale_cli-0.61.0/README.md +0 -179
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/__init__.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/commands/__init__.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/commands/deployment_commands.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/commands/development_commands.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/utils/__init__.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/utils/docker_utils.py +0 -0
- {quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/utils/project_manager.py +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: quickscale-cli
|
|
3
|
+
Version: 0.63.0
|
|
4
|
+
Summary: Command-line interface for QuickScale Django project generator
|
|
5
|
+
Home-page: https://github.com/Experto-AI/quickscale
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Keywords: django,cli,project-generator,saas
|
|
8
|
+
Author: Experto AI
|
|
9
|
+
Author-email: victor@experto.ai
|
|
10
|
+
Requires-Python: >=3.10,<4.0
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Framework :: Django
|
|
13
|
+
Classifier: Framework :: Django :: 4.2
|
|
14
|
+
Classifier: Framework :: Django :: 5.0
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
22
|
+
Requires-Dist: quickscale-core (>=0.63.0,<0.64.0)
|
|
23
|
+
Project-URL: Documentation, https://github.com/Experto-AI/quickscale/tree/main/docs
|
|
24
|
+
Project-URL: Repository, https://github.com/Experto-AI/quickscale
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "quickscale-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.63.0"
|
|
4
4
|
description = "Command-line interface for QuickScale Django project generator"
|
|
5
5
|
authors = ["Experto AI <victor@experto.ai>"]
|
|
6
6
|
license = "Apache-2.0"
|
|
7
|
-
readme = "README.md"
|
|
8
7
|
keywords = ["django", "cli", "project-generator", "saas"]
|
|
9
8
|
homepage = "https://github.com/Experto-AI/quickscale"
|
|
10
9
|
repository = "https://github.com/Experto-AI/quickscale"
|
|
@@ -26,7 +25,7 @@ packages = [{include = "quickscale_cli", from = "src"}]
|
|
|
26
25
|
[tool.poetry.dependencies]
|
|
27
26
|
python = "^3.10"
|
|
28
27
|
click = "^8.1.0"
|
|
29
|
-
quickscale-core = "^0.
|
|
28
|
+
quickscale-core = "^0.63.0"
|
|
30
29
|
|
|
31
30
|
[tool.poetry.group.dev.dependencies]
|
|
32
31
|
pytest = "^7.4.0"
|
|
@@ -106,4 +105,6 @@ module = "tests.*"
|
|
|
106
105
|
disallow_untyped_defs = false
|
|
107
106
|
check_untyped_defs = false
|
|
108
107
|
|
|
109
|
-
|
|
108
|
+
[[tool.mypy.overrides]]
|
|
109
|
+
module = "quickscale_core.*"
|
|
110
|
+
ignore_missing_imports = true
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# Auto-generated by scripts/version_tool.sh
|
|
2
|
-
__version__ = "0.
|
|
2
|
+
__version__ = "0.63.0"
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
"""Module management commands for QuickScale CLI."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
|
|
8
|
+
from quickscale_core.config import add_module, load_config, update_module_version
|
|
9
|
+
from quickscale_core.utils.git_utils import (
|
|
10
|
+
GitError,
|
|
11
|
+
check_remote_branch_exists,
|
|
12
|
+
is_git_repo,
|
|
13
|
+
is_working_directory_clean,
|
|
14
|
+
run_git_subtree_add,
|
|
15
|
+
run_git_subtree_pull,
|
|
16
|
+
run_git_subtree_push,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Available modules
|
|
20
|
+
AVAILABLE_MODULES = ["auth", "billing", "teams"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def configure_auth_module() -> dict[str, Any]:
|
|
24
|
+
"""Interactive configuration for auth module"""
|
|
25
|
+
click.echo("\n⚙️ Configuring auth module...")
|
|
26
|
+
click.echo("Answer these questions to customize the authentication setup:\n")
|
|
27
|
+
|
|
28
|
+
config = {
|
|
29
|
+
"allow_registration": click.confirm("Enable user registration?", default=True),
|
|
30
|
+
"email_verification": click.prompt(
|
|
31
|
+
"Email verification",
|
|
32
|
+
type=click.Choice(["none", "optional", "mandatory"], case_sensitive=False),
|
|
33
|
+
default="none",
|
|
34
|
+
show_choices=True,
|
|
35
|
+
),
|
|
36
|
+
"authentication_method": click.prompt(
|
|
37
|
+
"Authentication method",
|
|
38
|
+
type=click.Choice(["email", "username", "both"], case_sensitive=False),
|
|
39
|
+
default="email",
|
|
40
|
+
show_choices=True,
|
|
41
|
+
),
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return config
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def apply_auth_configuration(project_path: Path, config: dict[str, Any]) -> None:
|
|
48
|
+
"""Apply auth module configuration to project settings"""
|
|
49
|
+
settings_path = project_path / "settings.py"
|
|
50
|
+
urls_path = project_path / "urls.py"
|
|
51
|
+
|
|
52
|
+
if not settings_path.exists():
|
|
53
|
+
click.secho("⚠️ Warning: settings.py not found, skipping auto-configuration", fg="yellow")
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
# Read settings.py
|
|
57
|
+
with open(settings_path) as f:
|
|
58
|
+
settings_content = f.read()
|
|
59
|
+
|
|
60
|
+
# Check if already configured
|
|
61
|
+
if "quickscale_modules_auth" in settings_content:
|
|
62
|
+
click.echo("ℹ️ Auth module already configured in settings.py")
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
# Add required apps to INSTALLED_APPS
|
|
66
|
+
installed_apps_addition = """
|
|
67
|
+
# QuickScale Auth Module - Added by quickscale embed
|
|
68
|
+
INSTALLED_APPS += [
|
|
69
|
+
"django.contrib.sites", # Required by allauth
|
|
70
|
+
"allauth",
|
|
71
|
+
"allauth.account",
|
|
72
|
+
"quickscale_modules_auth",
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
# Authentication Configuration
|
|
76
|
+
AUTHENTICATION_BACKENDS = [
|
|
77
|
+
"django.contrib.auth.backends.ModelBackend",
|
|
78
|
+
"allauth.account.auth_backends.AuthenticationBackend",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
# Custom User Model
|
|
82
|
+
AUTH_USER_MODEL = "quickscale_modules_auth.User"
|
|
83
|
+
|
|
84
|
+
# Site ID (required by django.contrib.sites)
|
|
85
|
+
SITE_ID = 1
|
|
86
|
+
|
|
87
|
+
# Allauth Settings
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
# Add configuration based on user choices
|
|
91
|
+
if config["authentication_method"] == "email":
|
|
92
|
+
installed_apps_addition += 'ACCOUNT_AUTHENTICATION_METHOD = "email"\n'
|
|
93
|
+
installed_apps_addition += "ACCOUNT_USERNAME_REQUIRED = False\n"
|
|
94
|
+
installed_apps_addition += "ACCOUNT_EMAIL_REQUIRED = True\n"
|
|
95
|
+
elif config["authentication_method"] == "username":
|
|
96
|
+
installed_apps_addition += 'ACCOUNT_AUTHENTICATION_METHOD = "username"\n'
|
|
97
|
+
installed_apps_addition += "ACCOUNT_USERNAME_REQUIRED = True\n"
|
|
98
|
+
installed_apps_addition += "ACCOUNT_EMAIL_REQUIRED = False\n"
|
|
99
|
+
else: # both
|
|
100
|
+
installed_apps_addition += 'ACCOUNT_AUTHENTICATION_METHOD = "email"\n'
|
|
101
|
+
installed_apps_addition += "ACCOUNT_USERNAME_REQUIRED = True\n"
|
|
102
|
+
installed_apps_addition += "ACCOUNT_EMAIL_REQUIRED = True\n"
|
|
103
|
+
|
|
104
|
+
installed_apps_addition += f'ACCOUNT_EMAIL_VERIFICATION = "{config["email_verification"]}"\n'
|
|
105
|
+
installed_apps_addition += f'ACCOUNT_ALLOW_REGISTRATION = {config["allow_registration"]}\n'
|
|
106
|
+
installed_apps_addition += (
|
|
107
|
+
'ACCOUNT_ADAPTER = "quickscale_modules_auth.adapters.QuickscaleAccountAdapter"\n'
|
|
108
|
+
)
|
|
109
|
+
installed_apps_addition += (
|
|
110
|
+
'ACCOUNT_SIGNUP_FORM_CLASS = "quickscale_modules_auth.forms.SignupForm"\n'
|
|
111
|
+
)
|
|
112
|
+
installed_apps_addition += 'LOGIN_REDIRECT_URL = "/accounts/profile/"\n'
|
|
113
|
+
installed_apps_addition += 'LOGOUT_REDIRECT_URL = "/"\n'
|
|
114
|
+
installed_apps_addition += "SESSION_COOKIE_AGE = 1209600 # 2 weeks\n"
|
|
115
|
+
|
|
116
|
+
# Append to settings.py
|
|
117
|
+
with open(settings_path, "a") as f:
|
|
118
|
+
f.write("\n" + installed_apps_addition)
|
|
119
|
+
|
|
120
|
+
click.secho(" ✅ Updated settings.py with auth configuration", fg="green")
|
|
121
|
+
|
|
122
|
+
# Update urls.py
|
|
123
|
+
if urls_path.exists():
|
|
124
|
+
with open(urls_path) as f:
|
|
125
|
+
urls_content = f.read()
|
|
126
|
+
|
|
127
|
+
if "quickscale_modules_auth" not in urls_content:
|
|
128
|
+
# Find urlpatterns and add auth URLs
|
|
129
|
+
if "urlpatterns = [" in urls_content:
|
|
130
|
+
urls_addition = (
|
|
131
|
+
' path("accounts/", include("quickscale_modules_auth.urls")), # Auth URLs\n'
|
|
132
|
+
)
|
|
133
|
+
urls_content = urls_content.replace(
|
|
134
|
+
"urlpatterns = [", "urlpatterns = [\n" + urls_addition
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
with open(urls_path, "w") as f:
|
|
138
|
+
f.write(urls_content)
|
|
139
|
+
|
|
140
|
+
click.secho(" ✅ Updated urls.py with auth URLs", fg="green")
|
|
141
|
+
|
|
142
|
+
# Show configuration summary
|
|
143
|
+
click.echo("\n📋 Configuration applied:")
|
|
144
|
+
click.echo(f" • Registration: {'Enabled' if config['allow_registration'] else 'Disabled'}")
|
|
145
|
+
click.echo(f" • Email verification: {config['email_verification']}")
|
|
146
|
+
click.echo(f" • Authentication: {config['authentication_method']}")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
MODULE_CONFIGURATORS = {
|
|
150
|
+
"auth": (configure_auth_module, apply_auth_configuration),
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@click.command()
|
|
155
|
+
@click.option(
|
|
156
|
+
"--module",
|
|
157
|
+
required=True,
|
|
158
|
+
type=click.Choice(AVAILABLE_MODULES, case_sensitive=False),
|
|
159
|
+
help="Module name to embed",
|
|
160
|
+
)
|
|
161
|
+
@click.option(
|
|
162
|
+
"--remote",
|
|
163
|
+
default="https://github.com/Experto-AI/quickscale.git",
|
|
164
|
+
help="Git remote URL (default: QuickScale repository)",
|
|
165
|
+
)
|
|
166
|
+
def embed(module: str, remote: str) -> None:
|
|
167
|
+
r"""
|
|
168
|
+
Embed a QuickScale module into your project via git subtree.
|
|
169
|
+
|
|
170
|
+
\b
|
|
171
|
+
Examples:
|
|
172
|
+
quickscale embed --module auth
|
|
173
|
+
quickscale embed --module billing
|
|
174
|
+
|
|
175
|
+
\b
|
|
176
|
+
Available modules (v0.62.0 placeholders):
|
|
177
|
+
- auth: Authentication with django-allauth (placeholder)
|
|
178
|
+
- billing: Stripe integration with dj-stripe (placeholder)
|
|
179
|
+
- teams: Multi-tenancy and team management (placeholder)
|
|
180
|
+
|
|
181
|
+
\b
|
|
182
|
+
Note: In v0.62.0, modules contain only placeholder READMEs explaining
|
|
183
|
+
they're not yet implemented. Full implementations coming in v0.63.0+.
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
# Validate git repository
|
|
187
|
+
if not is_git_repo():
|
|
188
|
+
click.secho("❌ Error: Not a git repository", fg="red", err=True)
|
|
189
|
+
click.echo("\n💡 Tip: Run 'git init' to initialize a git repository", err=True)
|
|
190
|
+
raise click.Abort()
|
|
191
|
+
|
|
192
|
+
# Check working directory is clean
|
|
193
|
+
if not is_working_directory_clean():
|
|
194
|
+
click.secho("❌ Error: Working directory has uncommitted changes", fg="red", err=True)
|
|
195
|
+
click.echo("\n💡 Tip: Commit or stash your changes before embedding modules", err=True)
|
|
196
|
+
raise click.Abort()
|
|
197
|
+
|
|
198
|
+
# Check if module already exists
|
|
199
|
+
module_path = Path.cwd() / "modules" / module
|
|
200
|
+
if module_path.exists():
|
|
201
|
+
click.secho(
|
|
202
|
+
f"❌ Error: Module '{module}' already exists at {module_path}", fg="red", err=True
|
|
203
|
+
)
|
|
204
|
+
click.echo("\n💡 Tip: Remove the existing module directory first", err=True)
|
|
205
|
+
raise click.Abort()
|
|
206
|
+
|
|
207
|
+
# Check if branch exists on remote
|
|
208
|
+
branch = f"splits/{module}-module"
|
|
209
|
+
click.echo(f"🔍 Checking if {branch} exists on remote...")
|
|
210
|
+
|
|
211
|
+
if not check_remote_branch_exists(remote, branch):
|
|
212
|
+
click.secho(
|
|
213
|
+
f"❌ Error: Module '{module}' is not yet implemented",
|
|
214
|
+
fg="red",
|
|
215
|
+
err=True,
|
|
216
|
+
)
|
|
217
|
+
click.echo(
|
|
218
|
+
f"\n💡 The '{module}' module infrastructure is ready but contains "
|
|
219
|
+
"only placeholder files.",
|
|
220
|
+
err=True,
|
|
221
|
+
)
|
|
222
|
+
click.echo(" Full implementation coming in v0.63.0+", err=True)
|
|
223
|
+
click.echo(f"\n📖 Branch '{branch}' does not exist on remote: {remote}", err=True)
|
|
224
|
+
raise click.Abort()
|
|
225
|
+
|
|
226
|
+
# Interactive module configuration (v0.63.0+)
|
|
227
|
+
config = {}
|
|
228
|
+
if module in MODULE_CONFIGURATORS:
|
|
229
|
+
configurator, applier = MODULE_CONFIGURATORS[module]
|
|
230
|
+
config = configurator()
|
|
231
|
+
|
|
232
|
+
# Embed module via git subtree
|
|
233
|
+
prefix = f"modules/{module}"
|
|
234
|
+
click.echo(f"\n📦 Embedding {module} module from {branch}...")
|
|
235
|
+
|
|
236
|
+
run_git_subtree_add(prefix=prefix, remote=remote, branch=branch, squash=True)
|
|
237
|
+
|
|
238
|
+
# Update configuration tracking
|
|
239
|
+
add_module(
|
|
240
|
+
module_name=module,
|
|
241
|
+
prefix=prefix,
|
|
242
|
+
branch=branch,
|
|
243
|
+
version="v0.63.0",
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Apply module-specific configuration
|
|
247
|
+
if module in MODULE_CONFIGURATORS and config:
|
|
248
|
+
_, applier = MODULE_CONFIGURATORS[module]
|
|
249
|
+
project_root = Path.cwd()
|
|
250
|
+
applier(project_root, config)
|
|
251
|
+
|
|
252
|
+
# Success message
|
|
253
|
+
click.secho(f"\n✅ Module '{module}' embedded successfully!", fg="green", bold=True)
|
|
254
|
+
click.echo(f" Location: {module_path}")
|
|
255
|
+
click.echo(f" Branch: {branch}")
|
|
256
|
+
|
|
257
|
+
# Module-specific next steps
|
|
258
|
+
click.echo("\n📋 Next steps:")
|
|
259
|
+
if module == "auth":
|
|
260
|
+
click.echo(f" 1. Review module code in modules/{module}/")
|
|
261
|
+
click.echo(" 2. Run migrations: python manage.py migrate")
|
|
262
|
+
click.echo(" 3. Create superuser (optional): python manage.py createsuperuser")
|
|
263
|
+
click.echo(" 4. Visit http://localhost:8000/accounts/login/")
|
|
264
|
+
click.echo("\n� Documentation: modules/auth/README.md")
|
|
265
|
+
else:
|
|
266
|
+
click.echo(f" 1. Review the module code in modules/{module}/")
|
|
267
|
+
click.echo(f" 2. Follow setup instructions in modules/{module}/README.md")
|
|
268
|
+
click.echo(" 3. Run migrations: python manage.py migrate")
|
|
269
|
+
|
|
270
|
+
except GitError as e:
|
|
271
|
+
click.secho(f"❌ Git error: {e}", fg="red", err=True)
|
|
272
|
+
raise click.Abort()
|
|
273
|
+
except Exception as e:
|
|
274
|
+
click.secho(f"❌ Unexpected error: {e}", fg="red", err=True)
|
|
275
|
+
raise click.Abort()
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@click.command()
|
|
279
|
+
@click.option(
|
|
280
|
+
"--no-preview",
|
|
281
|
+
is_flag=True,
|
|
282
|
+
help="Skip diff preview before updating",
|
|
283
|
+
)
|
|
284
|
+
def update(no_preview: bool) -> None:
|
|
285
|
+
r"""
|
|
286
|
+
Update all installed QuickScale modules to their latest versions.
|
|
287
|
+
|
|
288
|
+
\b
|
|
289
|
+
Examples:
|
|
290
|
+
quickscale update # Update with diff preview
|
|
291
|
+
quickscale update --no-preview # Update without preview
|
|
292
|
+
|
|
293
|
+
\b
|
|
294
|
+
This command:
|
|
295
|
+
- Reads installed modules from .quickscale/config.yml
|
|
296
|
+
- Updates ONLY modules you've explicitly installed
|
|
297
|
+
- Shows a diff preview before updating (unless --no-preview)
|
|
298
|
+
- Updates the installed version in config after successful update
|
|
299
|
+
"""
|
|
300
|
+
try:
|
|
301
|
+
# Validate git repository
|
|
302
|
+
if not is_git_repo():
|
|
303
|
+
click.secho("❌ Error: Not a git repository", fg="red", err=True)
|
|
304
|
+
click.echo("\n💡 Tip: This command must be run from a git repository", err=True)
|
|
305
|
+
raise click.Abort()
|
|
306
|
+
|
|
307
|
+
# Check working directory is clean
|
|
308
|
+
if not is_working_directory_clean():
|
|
309
|
+
click.secho("❌ Error: Working directory has uncommitted changes", fg="red", err=True)
|
|
310
|
+
click.echo("\n💡 Tip: Commit or stash your changes before updating modules", err=True)
|
|
311
|
+
raise click.Abort()
|
|
312
|
+
|
|
313
|
+
# Load configuration
|
|
314
|
+
config = load_config()
|
|
315
|
+
|
|
316
|
+
if not config.modules:
|
|
317
|
+
click.secho("✅ No modules installed. Nothing to update.", fg="green")
|
|
318
|
+
click.echo("\n💡 Tip: Install modules with 'quickscale embed --module <name>'")
|
|
319
|
+
return
|
|
320
|
+
|
|
321
|
+
# Show installed modules
|
|
322
|
+
click.echo(f"📦 Found {len(config.modules)} installed module(s):")
|
|
323
|
+
for name, info in config.modules.items():
|
|
324
|
+
click.echo(f" - {name} ({info.installed_version})")
|
|
325
|
+
|
|
326
|
+
if not no_preview:
|
|
327
|
+
click.echo("\n🔍 Preview mode: Changes will be shown before updating")
|
|
328
|
+
|
|
329
|
+
# Confirm update
|
|
330
|
+
if not click.confirm("\n❓ Continue with update?"):
|
|
331
|
+
click.echo("❌ Update cancelled")
|
|
332
|
+
return
|
|
333
|
+
|
|
334
|
+
# Update each module
|
|
335
|
+
for name, info in config.modules.items():
|
|
336
|
+
click.echo(f"\n📥 Updating {name} module...")
|
|
337
|
+
|
|
338
|
+
try:
|
|
339
|
+
output = run_git_subtree_pull(
|
|
340
|
+
prefix=info.prefix,
|
|
341
|
+
remote=config.default_remote,
|
|
342
|
+
branch=info.branch,
|
|
343
|
+
squash=True,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Update version in config
|
|
347
|
+
update_module_version(name, "v0.62.0") # Placeholder version
|
|
348
|
+
|
|
349
|
+
click.secho(f"✅ Updated {name} successfully", fg="green")
|
|
350
|
+
|
|
351
|
+
if output and not no_preview:
|
|
352
|
+
click.echo("\n📋 Changes summary:")
|
|
353
|
+
click.echo(output[:500]) # Show first 500 chars
|
|
354
|
+
|
|
355
|
+
except GitError as e:
|
|
356
|
+
click.secho(f"❌ Failed to update {name}: {e}", fg="red", err=True)
|
|
357
|
+
click.echo(f"💡 Tip: Check for conflicts in modules/{name}/", err=True)
|
|
358
|
+
continue
|
|
359
|
+
|
|
360
|
+
click.secho("\n🎉 Module update complete!", fg="green", bold=True)
|
|
361
|
+
|
|
362
|
+
except GitError as e:
|
|
363
|
+
click.secho(f"❌ Git error: {e}", fg="red", err=True)
|
|
364
|
+
raise click.Abort()
|
|
365
|
+
except Exception as e:
|
|
366
|
+
click.secho(f"❌ Unexpected error: {e}", fg="red", err=True)
|
|
367
|
+
raise click.Abort()
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@click.command()
|
|
371
|
+
@click.option(
|
|
372
|
+
"--module",
|
|
373
|
+
required=True,
|
|
374
|
+
type=click.Choice(AVAILABLE_MODULES, case_sensitive=False),
|
|
375
|
+
help="Module name to push changes for",
|
|
376
|
+
)
|
|
377
|
+
@click.option(
|
|
378
|
+
"--branch",
|
|
379
|
+
help="Feature branch name (default: feature/<module>-improvements)",
|
|
380
|
+
)
|
|
381
|
+
@click.option(
|
|
382
|
+
"--remote",
|
|
383
|
+
default="https://github.com/Experto-AI/quickscale.git",
|
|
384
|
+
help="Git remote URL (default: QuickScale repository)",
|
|
385
|
+
)
|
|
386
|
+
def push(module: str, branch: str, remote: str) -> None:
|
|
387
|
+
r"""
|
|
388
|
+
Push your local module changes to a feature branch for contribution.
|
|
389
|
+
|
|
390
|
+
\b
|
|
391
|
+
Examples:
|
|
392
|
+
quickscale push --module auth
|
|
393
|
+
quickscale push --module auth --branch feature/fix-email-validation
|
|
394
|
+
|
|
395
|
+
\b
|
|
396
|
+
Workflow:
|
|
397
|
+
1. This command pushes your changes to a feature branch
|
|
398
|
+
2. You'll need to create a pull request manually on GitHub
|
|
399
|
+
3. Maintainers review and merge to main branch
|
|
400
|
+
4. Auto-split updates the module's split branch
|
|
401
|
+
|
|
402
|
+
\b
|
|
403
|
+
Note: You must have write access to the repository to push.
|
|
404
|
+
For external contributions, fork the repository first.
|
|
405
|
+
"""
|
|
406
|
+
try:
|
|
407
|
+
# Validate git repository
|
|
408
|
+
if not is_git_repo():
|
|
409
|
+
click.secho("❌ Error: Not a git repository", fg="red", err=True)
|
|
410
|
+
raise click.Abort()
|
|
411
|
+
|
|
412
|
+
# Check if module is installed
|
|
413
|
+
config = load_config()
|
|
414
|
+
if module not in config.modules:
|
|
415
|
+
click.secho(f"❌ Error: Module '{module}' is not installed", fg="red", err=True)
|
|
416
|
+
click.echo(
|
|
417
|
+
f"\n💡 Tip: Install the module first with 'quickscale embed --module {module}'",
|
|
418
|
+
err=True,
|
|
419
|
+
)
|
|
420
|
+
raise click.Abort()
|
|
421
|
+
|
|
422
|
+
module_info = config.modules[module]
|
|
423
|
+
|
|
424
|
+
# Default branch name
|
|
425
|
+
if not branch:
|
|
426
|
+
branch = f"feature/{module}-improvements"
|
|
427
|
+
|
|
428
|
+
# Show what will be pushed
|
|
429
|
+
click.echo(f"📤 Preparing to push changes for module: {module}")
|
|
430
|
+
click.echo(f" Local prefix: {module_info.prefix}")
|
|
431
|
+
click.echo(f" Target branch: {branch}")
|
|
432
|
+
click.echo(f" Remote: {remote}")
|
|
433
|
+
|
|
434
|
+
# Confirm push
|
|
435
|
+
if not click.confirm("\n❓ Continue with push?"):
|
|
436
|
+
click.echo("❌ Push cancelled")
|
|
437
|
+
return
|
|
438
|
+
|
|
439
|
+
# Push subtree
|
|
440
|
+
click.echo(f"\n🚀 Pushing to {branch}...")
|
|
441
|
+
run_git_subtree_push(prefix=module_info.prefix, remote=remote, branch=branch)
|
|
442
|
+
|
|
443
|
+
# Success message
|
|
444
|
+
click.secho("\n✅ Changes pushed successfully!", fg="green", bold=True)
|
|
445
|
+
click.echo("\n📋 Next steps:")
|
|
446
|
+
click.echo(" 1. Create a pull request on GitHub:")
|
|
447
|
+
click.echo(f" https://github.com/Experto-AI/quickscale/pull/new/{branch}")
|
|
448
|
+
click.echo(" 2. Describe your changes and submit for review")
|
|
449
|
+
click.echo(" 3. After merge, the split branch will auto-update")
|
|
450
|
+
|
|
451
|
+
except GitError as e:
|
|
452
|
+
click.secho(f"❌ Git error: {e}", fg="red", err=True)
|
|
453
|
+
click.echo("\n💡 Tip: Make sure you have write access to the repository", err=True)
|
|
454
|
+
raise click.Abort()
|
|
455
|
+
except Exception as e:
|
|
456
|
+
click.secho(f"❌ Unexpected error: {e}", fg="red", err=True)
|
|
457
|
+
raise click.Abort()
|
|
@@ -8,13 +8,14 @@ import quickscale_cli
|
|
|
8
8
|
import quickscale_core
|
|
9
9
|
from quickscale_cli.commands.deployment_commands import deploy
|
|
10
10
|
from quickscale_cli.commands.development_commands import down, logs, manage, ps, shell, up
|
|
11
|
+
from quickscale_cli.commands.module_commands import embed, push, update
|
|
11
12
|
from quickscale_core.generator import ProjectGenerator
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class InitCommand(click.Command):
|
|
15
16
|
"""Custom init command with enhanced error messages."""
|
|
16
17
|
|
|
17
|
-
def parse_args(self, ctx, args):
|
|
18
|
+
def parse_args(self, ctx: click.Context, args: list[str]) -> list[str]:
|
|
18
19
|
"""Override parse_args to provide better error messages."""
|
|
19
20
|
try:
|
|
20
21
|
return super().parse_args(ctx, args)
|
|
@@ -54,6 +55,11 @@ cli.add_command(ps)
|
|
|
54
55
|
# Register deployment commands
|
|
55
56
|
cli.add_command(deploy)
|
|
56
57
|
|
|
58
|
+
# Register module management commands
|
|
59
|
+
cli.add_command(embed)
|
|
60
|
+
cli.add_command(update)
|
|
61
|
+
cli.add_command(push)
|
|
62
|
+
|
|
57
63
|
|
|
58
64
|
@cli.command(cls=InitCommand)
|
|
59
65
|
@click.argument("project_name", required=True, metavar="PROJECT_NAME")
|
|
@@ -64,7 +70,7 @@ cli.add_command(deploy)
|
|
|
64
70
|
help="Theme to use for the project (default: starter_html)",
|
|
65
71
|
)
|
|
66
72
|
def init(project_name: str, theme: str) -> None:
|
|
67
|
-
"""
|
|
73
|
+
r"""
|
|
68
74
|
Generate a new Django project with production-ready configurations.
|
|
69
75
|
|
|
70
76
|
\b
|
|
@@ -24,7 +24,8 @@ def get_railway_cli_version() -> str | None:
|
|
|
24
24
|
"""
|
|
25
25
|
Get the current Railway CLI version string.
|
|
26
26
|
|
|
27
|
-
Returns
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
28
29
|
Version string (e.g., "4.0.0") or None if not installed or error
|
|
29
30
|
|
|
30
31
|
"""
|
|
@@ -51,7 +52,8 @@ def install_railway_cli() -> bool:
|
|
|
51
52
|
"""
|
|
52
53
|
Install Railway CLI via npm.
|
|
53
54
|
|
|
54
|
-
Returns
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
55
57
|
True if installation successful, False otherwise
|
|
56
58
|
|
|
57
59
|
"""
|
|
@@ -71,7 +73,8 @@ def upgrade_railway_cli() -> bool:
|
|
|
71
73
|
"""
|
|
72
74
|
Upgrade Railway CLI to the latest version via npm.
|
|
73
75
|
|
|
74
|
-
Returns
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
75
78
|
True if upgrade successful, False otherwise
|
|
76
79
|
|
|
77
80
|
"""
|
|
@@ -93,7 +96,8 @@ def login_railway_cli_browserless() -> bool:
|
|
|
93
96
|
|
|
94
97
|
This will prompt the user to visit a URL and enter a pairing code.
|
|
95
98
|
|
|
96
|
-
Returns
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
97
101
|
True if login successful, False otherwise
|
|
98
102
|
|
|
99
103
|
"""
|
|
@@ -207,11 +211,13 @@ def run_railway_command(
|
|
|
207
211
|
Execute Railway CLI command with error handling.
|
|
208
212
|
|
|
209
213
|
Args:
|
|
214
|
+
----
|
|
210
215
|
args: Command arguments to pass to railway CLI
|
|
211
216
|
timeout: Command timeout in seconds
|
|
212
217
|
interactive: If True, run command interactively without capturing output
|
|
213
218
|
|
|
214
219
|
Returns:
|
|
220
|
+
-------
|
|
215
221
|
CompletedProcess result
|
|
216
222
|
|
|
217
223
|
"""
|
|
@@ -247,6 +253,7 @@ def set_railway_variable(key: str, value: str, service: str | None = None) -> bo
|
|
|
247
253
|
Set Railway environment variable.
|
|
248
254
|
|
|
249
255
|
Args:
|
|
256
|
+
----
|
|
250
257
|
key: Environment variable name
|
|
251
258
|
value: Environment variable value
|
|
252
259
|
service: Service name to set variable for (optional)
|
|
@@ -272,10 +279,12 @@ def set_railway_variables_batch(
|
|
|
272
279
|
triggering a deployment for each variable.
|
|
273
280
|
|
|
274
281
|
Args:
|
|
282
|
+
----
|
|
275
283
|
variables: Dictionary of environment variable names and values
|
|
276
284
|
service: Service name to set variables for (optional)
|
|
277
285
|
|
|
278
286
|
Returns:
|
|
287
|
+
-------
|
|
279
288
|
Tuple of (success, failed_keys)
|
|
280
289
|
- success: True if all variables were set successfully
|
|
281
290
|
- failed_keys: List of variable keys that failed to set
|
|
@@ -327,9 +336,11 @@ def get_deployment_url(service: str | None = None) -> str | None:
|
|
|
327
336
|
Get deployment URL from Railway project.
|
|
328
337
|
|
|
329
338
|
Args:
|
|
339
|
+
----
|
|
330
340
|
service: Service name (unused - kept for compatibility)
|
|
331
341
|
|
|
332
342
|
Note:
|
|
343
|
+
----
|
|
333
344
|
Railway CLI v4's `status` command does not accept --service flag.
|
|
334
345
|
This function returns the first deployment URL found.
|
|
335
346
|
|
|
@@ -356,9 +367,11 @@ def get_app_service_name(project_name: str | None = None) -> str:
|
|
|
356
367
|
Determine the app service name for Railway deployment.
|
|
357
368
|
|
|
358
369
|
Args:
|
|
370
|
+
----
|
|
359
371
|
project_name: Project name (defaults to current directory name)
|
|
360
372
|
|
|
361
373
|
Returns:
|
|
374
|
+
-------
|
|
362
375
|
Service name to use for the app
|
|
363
376
|
|
|
364
377
|
"""
|
|
@@ -376,9 +389,11 @@ def generate_railway_domain(service: str) -> str | None:
|
|
|
376
389
|
Generate Railway public domain for a service.
|
|
377
390
|
|
|
378
391
|
Args:
|
|
392
|
+
----
|
|
379
393
|
service: Service name to generate domain for
|
|
380
394
|
|
|
381
395
|
Returns:
|
|
396
|
+
-------
|
|
382
397
|
Generated domain URL or None if failed
|
|
383
398
|
|
|
384
399
|
"""
|
|
@@ -412,7 +427,8 @@ def check_uncommitted_changes() -> tuple[bool, str]:
|
|
|
412
427
|
"""
|
|
413
428
|
Check if there are uncommitted changes in the Git repository.
|
|
414
429
|
|
|
415
|
-
Returns
|
|
430
|
+
Returns
|
|
431
|
+
-------
|
|
416
432
|
Tuple of (has_changes, status_output)
|
|
417
433
|
- has_changes: True if there are uncommitted changes
|
|
418
434
|
- status_output: Git status output string
|
|
@@ -438,7 +454,8 @@ def verify_railway_json() -> tuple[bool, str]:
|
|
|
438
454
|
"""
|
|
439
455
|
Verify that railway.json exists and is valid JSON.
|
|
440
456
|
|
|
441
|
-
Returns
|
|
457
|
+
Returns
|
|
458
|
+
-------
|
|
442
459
|
Tuple of (is_valid, error_message)
|
|
443
460
|
- is_valid: True if file exists and is valid JSON
|
|
444
461
|
- error_message: Error description if validation fails, empty string otherwise
|
|
@@ -463,7 +480,8 @@ def verify_dockerfile() -> tuple[bool, str]:
|
|
|
463
480
|
"""
|
|
464
481
|
Verify that Dockerfile exists in the project root.
|
|
465
482
|
|
|
466
|
-
Returns
|
|
483
|
+
Returns
|
|
484
|
+
-------
|
|
467
485
|
Tuple of (exists, error_message)
|
|
468
486
|
- exists: True if Dockerfile exists
|
|
469
487
|
- error_message: Error description if check fails, empty string otherwise
|
|
@@ -487,7 +505,8 @@ def verify_railway_dependencies() -> tuple[bool, list[str]]:
|
|
|
487
505
|
- dj-database-url (Database URL parsing)
|
|
488
506
|
- whitenoise (Static file serving)
|
|
489
507
|
|
|
490
|
-
Returns
|
|
508
|
+
Returns
|
|
509
|
+
-------
|
|
491
510
|
Tuple of (all_present, missing_deps)
|
|
492
511
|
- all_present: True if all required dependencies are present
|
|
493
512
|
- missing_deps: List of missing dependency names
|
|
@@ -520,7 +539,8 @@ def check_poetry_lock_consistency() -> tuple[bool, str]:
|
|
|
520
539
|
"""
|
|
521
540
|
Check if poetry.lock is consistent with pyproject.toml.
|
|
522
541
|
|
|
523
|
-
Returns
|
|
542
|
+
Returns
|
|
543
|
+
-------
|
|
524
544
|
Tuple of (is_consistent, message)
|
|
525
545
|
- is_consistent: True if poetry.lock is consistent with pyproject.toml
|
|
526
546
|
- message: Status message
|
|
@@ -557,7 +577,8 @@ def fix_poetry_lock() -> tuple[bool, str]:
|
|
|
557
577
|
"""
|
|
558
578
|
Fix poetry.lock by running poetry lock --no-update.
|
|
559
579
|
|
|
560
|
-
Returns
|
|
580
|
+
Returns
|
|
581
|
+
-------
|
|
561
582
|
Tuple of (success, message)
|
|
562
583
|
- success: True if lock file was fixed successfully
|
|
563
584
|
- message: Status message
|
|
@@ -586,9 +607,11 @@ def get_railway_variables(service: str | None = None) -> dict[str, str] | None:
|
|
|
586
607
|
Get all environment variables for a Railway service.
|
|
587
608
|
|
|
588
609
|
Args:
|
|
610
|
+
----
|
|
589
611
|
service: Service name (optional)
|
|
590
612
|
|
|
591
613
|
Returns:
|
|
614
|
+
-------
|
|
592
615
|
Dictionary of variable names and values, or None if failed
|
|
593
616
|
|
|
594
617
|
"""
|
|
@@ -625,9 +648,11 @@ def link_database_to_service(service: str) -> tuple[bool, str]:
|
|
|
625
648
|
This creates a DATABASE_URL reference variable that points to the PostgreSQL service.
|
|
626
649
|
|
|
627
650
|
Args:
|
|
651
|
+
----
|
|
628
652
|
service: App service name to link database to
|
|
629
653
|
|
|
630
654
|
Returns:
|
|
655
|
+
-------
|
|
631
656
|
Tuple of (success, message)
|
|
632
657
|
- success: True if link was created successfully
|
|
633
658
|
- message: Status or error message
|
quickscale_cli-0.61.0/PKG-INFO
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: quickscale-cli
|
|
3
|
-
Version: 0.61.0
|
|
4
|
-
Summary: Command-line interface for QuickScale Django project generator
|
|
5
|
-
Home-page: https://github.com/Experto-AI/quickscale
|
|
6
|
-
License: Apache-2.0
|
|
7
|
-
Keywords: django,cli,project-generator,saas
|
|
8
|
-
Author: Experto AI
|
|
9
|
-
Author-email: victor@experto.ai
|
|
10
|
-
Requires-Python: >=3.10,<4.0
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Framework :: Django
|
|
13
|
-
Classifier: Framework :: Django :: 4.2
|
|
14
|
-
Classifier: Framework :: Django :: 5.0
|
|
15
|
-
Classifier: Intended Audience :: Developers
|
|
16
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
17
|
-
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
-
Requires-Dist: click (>=8.1.0,<9.0.0)
|
|
22
|
-
Requires-Dist: quickscale-core (>=0.61.0,<0.62.0)
|
|
23
|
-
Project-URL: Documentation, https://github.com/Experto-AI/quickscale/tree/main/docs
|
|
24
|
-
Project-URL: Repository, https://github.com/Experto-AI/quickscale
|
|
25
|
-
Description-Content-Type: text/markdown
|
|
26
|
-
|
|
27
|
-
# 🚀 QuickScale
|
|
28
|
-
|
|
29
|
-
<!--
|
|
30
|
-
README.md - User-Focused Introduction
|
|
31
|
-
|
|
32
|
-
PURPOSE: This file serves as the first contact point for users, developers, and evaluators visiting the QuickScale project.
|
|
33
|
-
|
|
34
|
-
CONTENT GUIDELINES:
|
|
35
|
-
- Keep content user-facing and accessible to newcomers
|
|
36
|
-
- Focus on "what" and "how to get started" rather than "why" or technical details
|
|
37
|
-
- Include quick examples and development workflows
|
|
38
|
-
- Avoid deep architectural explanations (those belong in DECISIONS.md)
|
|
39
|
-
- Avoid competitive analysis or strategic context (those belong in QUICKSCALE.md)
|
|
40
|
-
- Maximum length: ~200 lines to ensure quick readability
|
|
41
|
-
- Link to other documents for detailed information
|
|
42
|
-
|
|
43
|
-
TARGET AUDIENCE: New users, potential adopters, GitHub visitors, developers evaluating QuickScale
|
|
44
|
-
-->
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## QuickScale: Compose your Django SaaS.
|
|
49
|
-
|
|
50
|
-
QuickScale is a **composable Django framework** for building client SaaS applications. Start with a stable core, add reusable modules, customize themes, and deploy faster—while maintaining the flexibility to create commercial extensions and build a community ecosystem.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## What is QuickScale?
|
|
55
|
-
|
|
56
|
-
QuickScale is a **Django project generator** that creates production-ready SaaS applications with one command. Designed for **solo developers and development agencies**, it gives you:
|
|
57
|
-
|
|
58
|
-
- **Production-ready foundations**: Docker, PostgreSQL, testing, CI/CD, and security out-of-the-box
|
|
59
|
-
- **One-command deployment**: Deploy to Railway with `quickscale deploy railway`
|
|
60
|
-
- **Full ownership**: Generated projects are 100% yours to customize—no vendor lock-in
|
|
61
|
-
- **Standardized stack**: Build multiple client projects faster with consistent best practices
|
|
62
|
-
|
|
63
|
-
🧭 **Future Vision**: QuickScale will evolve to support reusable modules and themes. Today it's a personal toolkit; tomorrow it becomes a community platform when demand emerges. [Read the full evolution strategy](./docs/overview/quickscale.md#evolution-strategy-personal-toolkit-first).
|
|
64
|
-
|
|
65
|
-
## Documentation Guide
|
|
66
|
-
|
|
67
|
-
**Start here for your needs:**
|
|
68
|
-
- 📖 **New user?** You're in the right place. This README shows you what QuickScale is and how to get started.
|
|
69
|
-
- 🔧 **Need commands?** See [user_manual.md](./docs/technical/user_manual.md) for all commands and workflows
|
|
70
|
-
- 🚀 **Deploying to Railway?** See [railway.md](./docs/deployment/railway.md) for Railway deployment guide
|
|
71
|
-
- 📋 **Planning a feature?** Check [decisions.md](./docs/technical/decisions.md) for the authoritative MVP scope and technical rules
|
|
72
|
-
- 🗓️ **Timeline & tasks?** See [roadmap.md](./docs/technical/roadmap.md)
|
|
73
|
-
- 🏗️ **Project structure?** See [scaffolding.md](./docs/technical/scaffolding.md) for complete directory layouts
|
|
74
|
-
- 🎯 **Why QuickScale?** See [quickscale.md](./docs/overview/quickscale.md) for competitive positioning
|
|
75
|
-
|
|
76
|
-
**Quick Reference:**
|
|
77
|
-
- **MVP** = Phase 1 (Personal Toolkit)
|
|
78
|
-
- **Post-MVP** = Phase 2+ (Modules & Themes)
|
|
79
|
-
- **Generated Project** = Output of `quickscale init`
|
|
80
|
-
|
|
81
|
-
See [decisions.md - Glossary section](./docs/technical/decisions.md#document-responsibilities-short) for complete terminology and Single Source of Truth reference
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
### Primary Use Cases (MVP):
|
|
85
|
-
- **Solo Developer**: Build client projects faster with production-ready foundations
|
|
86
|
-
- **Development Agency**: Standardize your tech stack across client engagements
|
|
87
|
-
|
|
88
|
-
### Future Use Cases (Post-MVP):
|
|
89
|
-
- **Commercial Extension Developer**: Create and sell premium modules/themes
|
|
90
|
-
- **Open Source Contributor**: Extend the ecosystem with modules and themes
|
|
91
|
-
|
|
92
|
-
### Development Flow (MVP)
|
|
93
|
-
1. `quickscale init myapp`
|
|
94
|
-
- Generates the minimal Django starter described in the MVP Feature Matrix
|
|
95
|
-
- Ships with standalone `settings.py` by default; there is NO automatic settings inheritance. Advanced users who manually embed `quickscale_core` via git subtree may opt-in to inherit from `quickscale_core.settings` (see [decisions.md](./docs/technical/decisions.md#mvp-feature-matrix-authoritative)).
|
|
96
|
-
- **Optional**: Embed `quickscale_core` via git subtree after generation; follow the [Personal Toolkit workflow](./docs/technical/decisions.md#integration-note-personal-toolkit-git-subtree) for canonical commands and helper roadmap
|
|
97
|
-
2. Add your custom Django apps and features
|
|
98
|
-
3. Adopt optional inheritance or module extraction patterns only when you embed the core; the rules and best practices stay centralized in `DECISIONS.md`
|
|
99
|
-
4. Build your unique client application
|
|
100
|
-
5. Deploy to Railway with `quickscale deploy railway` (or use standard Django deployment)
|
|
101
|
-
|
|
102
|
-
ℹ️ QuickScale's MVP centers on the personal toolkit workflow. Extraction patterns, module packaging, and subtree helper command plans stay documented in `docs/technical/decisions.md` so this README can stay concise.
|
|
103
|
-
|
|
104
|
-
🔎 **Scope note**: The [MVP Feature Matrix](./docs/technical/decisions.md#mvp-feature-matrix-authoritative) is the single source of truth for what's in or out.
|
|
105
|
-
|
|
106
|
-
### What You Get
|
|
107
|
-
|
|
108
|
-
Running `quickscale init myapp` generates a **production-ready Django project** with:
|
|
109
|
-
|
|
110
|
-
- ✅ **Docker** setup (development + production)
|
|
111
|
-
- ✅ **PostgreSQL** configuration
|
|
112
|
-
- ✅ **Environment-based** settings (dev/prod split)
|
|
113
|
-
- ✅ **Security** best practices (SECRET_KEY, ALLOWED_HOSTS, etc.)
|
|
114
|
-
- ✅ **Testing** infrastructure (pytest + factory_boy)
|
|
115
|
-
- ✅ **CI/CD** pipeline (GitHub Actions)
|
|
116
|
-
- ✅ **Code quality** hooks (ruff format + ruff check)
|
|
117
|
-
- ✅ **Poetry** for dependency management
|
|
118
|
-
- ✅ **One-Command Deployment**: Deploy to Railway with `quickscale deploy railway` - fully automated setup
|
|
119
|
-
|
|
120
|
-
**See the complete project structure:** [scaffolding.md - Generated Project Output](./docs/technical/scaffolding.md#5-generated-project-output)
|
|
121
|
-
|
|
122
|
-
The generated project is **yours to own and modify** - no vendor lock-in, just Django best practices.
|
|
123
|
-
|
|
124
|
-
## Why QuickScale vs. Alternatives?
|
|
125
|
-
|
|
126
|
-
✅ **Faster than Cookiecutter** - One command vs. 30+ interactive prompts
|
|
127
|
-
✅ **More flexible than SaaS Pegasus** - Open source with full code ownership ($0 vs. $349+)
|
|
128
|
-
✅ **Simpler than building from scratch** - Production-ready in 5 minutes vs. days of setup
|
|
129
|
-
✅ **Railway deployment automation** - Competitors require manual platform configuration
|
|
130
|
-
|
|
131
|
-
**QuickScale is a development accelerator**, not a complete solution. You start with production-ready foundations and build your unique client application on top.
|
|
132
|
-
|
|
133
|
-
See [competitive_analysis.md](./docs/overview/competitive_analysis.md) for detailed comparison with SaaS Pegasus and Cookiecutter.
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
## Quick Start
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
# Install QuickScale globally
|
|
142
|
-
./scripts/install_global.sh
|
|
143
|
-
|
|
144
|
-
# Create your first project
|
|
145
|
-
quickscale init myapp
|
|
146
|
-
cd myapp
|
|
147
|
-
|
|
148
|
-
# Or choose a specific theme (v0.61.0+)
|
|
149
|
-
# quickscale init myapp --theme starter_html # Default HTML theme
|
|
150
|
-
# quickscale init myapp --theme starter_htmx # HTMX theme (coming in v0.67.0)
|
|
151
|
-
# quickscale init myapp --theme starter_react # React theme (coming in v0.68.0)
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**Choose your development workflow:**
|
|
155
|
-
|
|
156
|
-
### Option 1: Docker (Recommended for production parity)
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
# Start all services (web + database)
|
|
160
|
-
quickscale up
|
|
161
|
-
|
|
162
|
-
# Run migrations
|
|
163
|
-
quickscale manage migrate
|
|
164
|
-
|
|
165
|
-
# Create superuser
|
|
166
|
-
quickscale manage createsuperuser
|
|
167
|
-
|
|
168
|
-
# View logs
|
|
169
|
-
quickscale logs -f web
|
|
170
|
-
|
|
171
|
-
# Open a shell in the container
|
|
172
|
-
quickscale shell
|
|
173
|
-
|
|
174
|
-
# Stop services
|
|
175
|
-
quickscale down
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
**Visit http://localhost:8000** - Your app is running in Docker with PostgreSQL!
|
|
179
|
-
|
|
180
|
-
### Option 2: Native Poetry (Simpler for quick testing)
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
# Install dependencies
|
|
184
|
-
poetry install
|
|
185
|
-
|
|
186
|
-
# Run migrations
|
|
187
|
-
poetry run python manage.py migrate
|
|
188
|
-
|
|
189
|
-
# Start development server
|
|
190
|
-
poetry run python manage.py runserver
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**Visit http://localhost:8000** - Your app is running natively!
|
|
194
|
-
|
|
195
|
-
**For complete command reference and workflows**, see the [user_manual.md](./docs/technical/user_manual.md).
|
|
196
|
-
|
|
197
|
-
## Learn More
|
|
198
|
-
|
|
199
|
-
- **[decisions.md](./docs/technical/decisions.md)** - Technical specifications and implementation rules
|
|
200
|
-
- **[quickscale.md](./docs/overview/quickscale.md)** - Strategic vision and competitive positioning
|
|
201
|
-
- **[competitive_analysis.md](./docs/overview/competitive_analysis.md)** - Comparison vs SaaS Pegasus and alternatives
|
|
202
|
-
- **[roadmap.md](./docs/technical/roadmap.md)** - Development roadmap and implementation plan
|
|
203
|
-
- **[user_manual.md](./docs/technical/user_manual.md)** - Commands and workflows
|
|
204
|
-
- **[contributing.md](./docs/contrib/contributing.md)** - Development workflow and coding standards
|
|
205
|
-
|
|
206
|
-
|
quickscale_cli-0.61.0/README.md
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
# 🚀 QuickScale
|
|
2
|
-
|
|
3
|
-
<!--
|
|
4
|
-
README.md - User-Focused Introduction
|
|
5
|
-
|
|
6
|
-
PURPOSE: This file serves as the first contact point for users, developers, and evaluators visiting the QuickScale project.
|
|
7
|
-
|
|
8
|
-
CONTENT GUIDELINES:
|
|
9
|
-
- Keep content user-facing and accessible to newcomers
|
|
10
|
-
- Focus on "what" and "how to get started" rather than "why" or technical details
|
|
11
|
-
- Include quick examples and development workflows
|
|
12
|
-
- Avoid deep architectural explanations (those belong in DECISIONS.md)
|
|
13
|
-
- Avoid competitive analysis or strategic context (those belong in QUICKSCALE.md)
|
|
14
|
-
- Maximum length: ~200 lines to ensure quick readability
|
|
15
|
-
- Link to other documents for detailed information
|
|
16
|
-
|
|
17
|
-
TARGET AUDIENCE: New users, potential adopters, GitHub visitors, developers evaluating QuickScale
|
|
18
|
-
-->
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## QuickScale: Compose your Django SaaS.
|
|
23
|
-
|
|
24
|
-
QuickScale is a **composable Django framework** for building client SaaS applications. Start with a stable core, add reusable modules, customize themes, and deploy faster—while maintaining the flexibility to create commercial extensions and build a community ecosystem.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## What is QuickScale?
|
|
29
|
-
|
|
30
|
-
QuickScale is a **Django project generator** that creates production-ready SaaS applications with one command. Designed for **solo developers and development agencies**, it gives you:
|
|
31
|
-
|
|
32
|
-
- **Production-ready foundations**: Docker, PostgreSQL, testing, CI/CD, and security out-of-the-box
|
|
33
|
-
- **One-command deployment**: Deploy to Railway with `quickscale deploy railway`
|
|
34
|
-
- **Full ownership**: Generated projects are 100% yours to customize—no vendor lock-in
|
|
35
|
-
- **Standardized stack**: Build multiple client projects faster with consistent best practices
|
|
36
|
-
|
|
37
|
-
🧭 **Future Vision**: QuickScale will evolve to support reusable modules and themes. Today it's a personal toolkit; tomorrow it becomes a community platform when demand emerges. [Read the full evolution strategy](./docs/overview/quickscale.md#evolution-strategy-personal-toolkit-first).
|
|
38
|
-
|
|
39
|
-
## Documentation Guide
|
|
40
|
-
|
|
41
|
-
**Start here for your needs:**
|
|
42
|
-
- 📖 **New user?** You're in the right place. This README shows you what QuickScale is and how to get started.
|
|
43
|
-
- 🔧 **Need commands?** See [user_manual.md](./docs/technical/user_manual.md) for all commands and workflows
|
|
44
|
-
- 🚀 **Deploying to Railway?** See [railway.md](./docs/deployment/railway.md) for Railway deployment guide
|
|
45
|
-
- 📋 **Planning a feature?** Check [decisions.md](./docs/technical/decisions.md) for the authoritative MVP scope and technical rules
|
|
46
|
-
- 🗓️ **Timeline & tasks?** See [roadmap.md](./docs/technical/roadmap.md)
|
|
47
|
-
- 🏗️ **Project structure?** See [scaffolding.md](./docs/technical/scaffolding.md) for complete directory layouts
|
|
48
|
-
- 🎯 **Why QuickScale?** See [quickscale.md](./docs/overview/quickscale.md) for competitive positioning
|
|
49
|
-
|
|
50
|
-
**Quick Reference:**
|
|
51
|
-
- **MVP** = Phase 1 (Personal Toolkit)
|
|
52
|
-
- **Post-MVP** = Phase 2+ (Modules & Themes)
|
|
53
|
-
- **Generated Project** = Output of `quickscale init`
|
|
54
|
-
|
|
55
|
-
See [decisions.md - Glossary section](./docs/technical/decisions.md#document-responsibilities-short) for complete terminology and Single Source of Truth reference
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
### Primary Use Cases (MVP):
|
|
59
|
-
- **Solo Developer**: Build client projects faster with production-ready foundations
|
|
60
|
-
- **Development Agency**: Standardize your tech stack across client engagements
|
|
61
|
-
|
|
62
|
-
### Future Use Cases (Post-MVP):
|
|
63
|
-
- **Commercial Extension Developer**: Create and sell premium modules/themes
|
|
64
|
-
- **Open Source Contributor**: Extend the ecosystem with modules and themes
|
|
65
|
-
|
|
66
|
-
### Development Flow (MVP)
|
|
67
|
-
1. `quickscale init myapp`
|
|
68
|
-
- Generates the minimal Django starter described in the MVP Feature Matrix
|
|
69
|
-
- Ships with standalone `settings.py` by default; there is NO automatic settings inheritance. Advanced users who manually embed `quickscale_core` via git subtree may opt-in to inherit from `quickscale_core.settings` (see [decisions.md](./docs/technical/decisions.md#mvp-feature-matrix-authoritative)).
|
|
70
|
-
- **Optional**: Embed `quickscale_core` via git subtree after generation; follow the [Personal Toolkit workflow](./docs/technical/decisions.md#integration-note-personal-toolkit-git-subtree) for canonical commands and helper roadmap
|
|
71
|
-
2. Add your custom Django apps and features
|
|
72
|
-
3. Adopt optional inheritance or module extraction patterns only when you embed the core; the rules and best practices stay centralized in `DECISIONS.md`
|
|
73
|
-
4. Build your unique client application
|
|
74
|
-
5. Deploy to Railway with `quickscale deploy railway` (or use standard Django deployment)
|
|
75
|
-
|
|
76
|
-
ℹ️ QuickScale's MVP centers on the personal toolkit workflow. Extraction patterns, module packaging, and subtree helper command plans stay documented in `docs/technical/decisions.md` so this README can stay concise.
|
|
77
|
-
|
|
78
|
-
🔎 **Scope note**: The [MVP Feature Matrix](./docs/technical/decisions.md#mvp-feature-matrix-authoritative) is the single source of truth for what's in or out.
|
|
79
|
-
|
|
80
|
-
### What You Get
|
|
81
|
-
|
|
82
|
-
Running `quickscale init myapp` generates a **production-ready Django project** with:
|
|
83
|
-
|
|
84
|
-
- ✅ **Docker** setup (development + production)
|
|
85
|
-
- ✅ **PostgreSQL** configuration
|
|
86
|
-
- ✅ **Environment-based** settings (dev/prod split)
|
|
87
|
-
- ✅ **Security** best practices (SECRET_KEY, ALLOWED_HOSTS, etc.)
|
|
88
|
-
- ✅ **Testing** infrastructure (pytest + factory_boy)
|
|
89
|
-
- ✅ **CI/CD** pipeline (GitHub Actions)
|
|
90
|
-
- ✅ **Code quality** hooks (ruff format + ruff check)
|
|
91
|
-
- ✅ **Poetry** for dependency management
|
|
92
|
-
- ✅ **One-Command Deployment**: Deploy to Railway with `quickscale deploy railway` - fully automated setup
|
|
93
|
-
|
|
94
|
-
**See the complete project structure:** [scaffolding.md - Generated Project Output](./docs/technical/scaffolding.md#5-generated-project-output)
|
|
95
|
-
|
|
96
|
-
The generated project is **yours to own and modify** - no vendor lock-in, just Django best practices.
|
|
97
|
-
|
|
98
|
-
## Why QuickScale vs. Alternatives?
|
|
99
|
-
|
|
100
|
-
✅ **Faster than Cookiecutter** - One command vs. 30+ interactive prompts
|
|
101
|
-
✅ **More flexible than SaaS Pegasus** - Open source with full code ownership ($0 vs. $349+)
|
|
102
|
-
✅ **Simpler than building from scratch** - Production-ready in 5 minutes vs. days of setup
|
|
103
|
-
✅ **Railway deployment automation** - Competitors require manual platform configuration
|
|
104
|
-
|
|
105
|
-
**QuickScale is a development accelerator**, not a complete solution. You start with production-ready foundations and build your unique client application on top.
|
|
106
|
-
|
|
107
|
-
See [competitive_analysis.md](./docs/overview/competitive_analysis.md) for detailed comparison with SaaS Pegasus and Cookiecutter.
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
## Quick Start
|
|
113
|
-
|
|
114
|
-
```bash
|
|
115
|
-
# Install QuickScale globally
|
|
116
|
-
./scripts/install_global.sh
|
|
117
|
-
|
|
118
|
-
# Create your first project
|
|
119
|
-
quickscale init myapp
|
|
120
|
-
cd myapp
|
|
121
|
-
|
|
122
|
-
# Or choose a specific theme (v0.61.0+)
|
|
123
|
-
# quickscale init myapp --theme starter_html # Default HTML theme
|
|
124
|
-
# quickscale init myapp --theme starter_htmx # HTMX theme (coming in v0.67.0)
|
|
125
|
-
# quickscale init myapp --theme starter_react # React theme (coming in v0.68.0)
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
**Choose your development workflow:**
|
|
129
|
-
|
|
130
|
-
### Option 1: Docker (Recommended for production parity)
|
|
131
|
-
|
|
132
|
-
```bash
|
|
133
|
-
# Start all services (web + database)
|
|
134
|
-
quickscale up
|
|
135
|
-
|
|
136
|
-
# Run migrations
|
|
137
|
-
quickscale manage migrate
|
|
138
|
-
|
|
139
|
-
# Create superuser
|
|
140
|
-
quickscale manage createsuperuser
|
|
141
|
-
|
|
142
|
-
# View logs
|
|
143
|
-
quickscale logs -f web
|
|
144
|
-
|
|
145
|
-
# Open a shell in the container
|
|
146
|
-
quickscale shell
|
|
147
|
-
|
|
148
|
-
# Stop services
|
|
149
|
-
quickscale down
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
**Visit http://localhost:8000** - Your app is running in Docker with PostgreSQL!
|
|
153
|
-
|
|
154
|
-
### Option 2: Native Poetry (Simpler for quick testing)
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
# Install dependencies
|
|
158
|
-
poetry install
|
|
159
|
-
|
|
160
|
-
# Run migrations
|
|
161
|
-
poetry run python manage.py migrate
|
|
162
|
-
|
|
163
|
-
# Start development server
|
|
164
|
-
poetry run python manage.py runserver
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**Visit http://localhost:8000** - Your app is running natively!
|
|
168
|
-
|
|
169
|
-
**For complete command reference and workflows**, see the [user_manual.md](./docs/technical/user_manual.md).
|
|
170
|
-
|
|
171
|
-
## Learn More
|
|
172
|
-
|
|
173
|
-
- **[decisions.md](./docs/technical/decisions.md)** - Technical specifications and implementation rules
|
|
174
|
-
- **[quickscale.md](./docs/overview/quickscale.md)** - Strategic vision and competitive positioning
|
|
175
|
-
- **[competitive_analysis.md](./docs/overview/competitive_analysis.md)** - Comparison vs SaaS Pegasus and alternatives
|
|
176
|
-
- **[roadmap.md](./docs/technical/roadmap.md)** - Development roadmap and implementation plan
|
|
177
|
-
- **[user_manual.md](./docs/technical/user_manual.md)** - Commands and workflows
|
|
178
|
-
- **[contributing.md](./docs/contrib/contributing.md)** - Development workflow and coding standards
|
|
179
|
-
|
|
File without changes
|
|
File without changes
|
{quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/commands/deployment_commands.py
RENAMED
|
File without changes
|
{quickscale_cli-0.61.0 → quickscale_cli-0.63.0}/src/quickscale_cli/commands/development_commands.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|