createsonline 0.1.26__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.
- createsonline/__init__.py +46 -0
- createsonline/admin/__init__.py +7 -0
- createsonline/admin/content.py +526 -0
- createsonline/admin/crud.py +805 -0
- createsonline/admin/field_builder.py +559 -0
- createsonline/admin/integration.py +482 -0
- createsonline/admin/interface.py +2562 -0
- createsonline/admin/model_creator.py +513 -0
- createsonline/admin/model_manager.py +388 -0
- createsonline/admin/modern_dashboard.py +498 -0
- createsonline/admin/permissions.py +264 -0
- createsonline/admin/user_forms.py +594 -0
- createsonline/ai/__init__.py +202 -0
- createsonline/ai/fields.py +1226 -0
- createsonline/ai/orm.py +325 -0
- createsonline/ai/services.py +1244 -0
- createsonline/app.py +506 -0
- createsonline/auth/__init__.py +8 -0
- createsonline/auth/management.py +228 -0
- createsonline/auth/models.py +552 -0
- createsonline/cli/__init__.py +5 -0
- createsonline/cli/commands/__init__.py +122 -0
- createsonline/cli/commands/database.py +416 -0
- createsonline/cli/commands/info.py +173 -0
- createsonline/cli/commands/initdb.py +218 -0
- createsonline/cli/commands/project.py +545 -0
- createsonline/cli/commands/serve.py +173 -0
- createsonline/cli/commands/shell.py +93 -0
- createsonline/cli/commands/users.py +148 -0
- createsonline/cli/main.py +2041 -0
- createsonline/cli/manage.py +274 -0
- createsonline/config/__init__.py +9 -0
- createsonline/config/app.py +2577 -0
- createsonline/config/database.py +179 -0
- createsonline/config/docs.py +384 -0
- createsonline/config/errors.py +160 -0
- createsonline/config/orm.py +43 -0
- createsonline/config/request.py +93 -0
- createsonline/config/settings.py +176 -0
- createsonline/data/__init__.py +23 -0
- createsonline/data/dataframe.py +925 -0
- createsonline/data/io.py +453 -0
- createsonline/data/series.py +557 -0
- createsonline/database/__init__.py +60 -0
- createsonline/database/abstraction.py +440 -0
- createsonline/database/assistant.py +585 -0
- createsonline/database/fields.py +442 -0
- createsonline/database/migrations.py +132 -0
- createsonline/database/models.py +604 -0
- createsonline/database.py +438 -0
- createsonline/http/__init__.py +28 -0
- createsonline/http/client.py +535 -0
- createsonline/ml/__init__.py +55 -0
- createsonline/ml/classification.py +552 -0
- createsonline/ml/clustering.py +680 -0
- createsonline/ml/metrics.py +542 -0
- createsonline/ml/neural.py +560 -0
- createsonline/ml/preprocessing.py +784 -0
- createsonline/ml/regression.py +501 -0
- createsonline/performance/__init__.py +19 -0
- createsonline/performance/cache.py +444 -0
- createsonline/performance/compression.py +335 -0
- createsonline/performance/core.py +419 -0
- createsonline/project_init.py +789 -0
- createsonline/routing.py +528 -0
- createsonline/security/__init__.py +34 -0
- createsonline/security/core.py +811 -0
- createsonline/security/encryption.py +349 -0
- createsonline/server.py +295 -0
- createsonline/static/css/admin.css +263 -0
- createsonline/static/css/common.css +358 -0
- createsonline/static/css/dashboard.css +89 -0
- createsonline/static/favicon.ico +0 -0
- createsonline/static/icons/icon-128x128.png +0 -0
- createsonline/static/icons/icon-128x128.webp +0 -0
- createsonline/static/icons/icon-16x16.png +0 -0
- createsonline/static/icons/icon-16x16.webp +0 -0
- createsonline/static/icons/icon-180x180.png +0 -0
- createsonline/static/icons/icon-180x180.webp +0 -0
- createsonline/static/icons/icon-192x192.png +0 -0
- createsonline/static/icons/icon-192x192.webp +0 -0
- createsonline/static/icons/icon-256x256.png +0 -0
- createsonline/static/icons/icon-256x256.webp +0 -0
- createsonline/static/icons/icon-32x32.png +0 -0
- createsonline/static/icons/icon-32x32.webp +0 -0
- createsonline/static/icons/icon-384x384.png +0 -0
- createsonline/static/icons/icon-384x384.webp +0 -0
- createsonline/static/icons/icon-48x48.png +0 -0
- createsonline/static/icons/icon-48x48.webp +0 -0
- createsonline/static/icons/icon-512x512.png +0 -0
- createsonline/static/icons/icon-512x512.webp +0 -0
- createsonline/static/icons/icon-64x64.png +0 -0
- createsonline/static/icons/icon-64x64.webp +0 -0
- createsonline/static/image/android-chrome-192x192.png +0 -0
- createsonline/static/image/android-chrome-512x512.png +0 -0
- createsonline/static/image/apple-touch-icon.png +0 -0
- createsonline/static/image/favicon-16x16.png +0 -0
- createsonline/static/image/favicon-32x32.png +0 -0
- createsonline/static/image/favicon.ico +0 -0
- createsonline/static/image/favicon.svg +17 -0
- createsonline/static/image/icon-128x128.png +0 -0
- createsonline/static/image/icon-128x128.webp +0 -0
- createsonline/static/image/icon-16x16.png +0 -0
- createsonline/static/image/icon-16x16.webp +0 -0
- createsonline/static/image/icon-180x180.png +0 -0
- createsonline/static/image/icon-180x180.webp +0 -0
- createsonline/static/image/icon-192x192.png +0 -0
- createsonline/static/image/icon-192x192.webp +0 -0
- createsonline/static/image/icon-256x256.png +0 -0
- createsonline/static/image/icon-256x256.webp +0 -0
- createsonline/static/image/icon-32x32.png +0 -0
- createsonline/static/image/icon-32x32.webp +0 -0
- createsonline/static/image/icon-384x384.png +0 -0
- createsonline/static/image/icon-384x384.webp +0 -0
- createsonline/static/image/icon-48x48.png +0 -0
- createsonline/static/image/icon-48x48.webp +0 -0
- createsonline/static/image/icon-512x512.png +0 -0
- createsonline/static/image/icon-512x512.webp +0 -0
- createsonline/static/image/icon-64x64.png +0 -0
- createsonline/static/image/icon-64x64.webp +0 -0
- createsonline/static/image/logo-header-h100.png +0 -0
- createsonline/static/image/logo-header-h100.webp +0 -0
- createsonline/static/image/logo-header-h200@2x.png +0 -0
- createsonline/static/image/logo-header-h200@2x.webp +0 -0
- createsonline/static/image/logo.png +0 -0
- createsonline/static/js/admin.js +274 -0
- createsonline/static/site.webmanifest +35 -0
- createsonline/static/templates/admin/base.html +87 -0
- createsonline/static/templates/admin/dashboard.html +217 -0
- createsonline/static/templates/admin/model_form.html +270 -0
- createsonline/static/templates/admin/model_list.html +202 -0
- createsonline/static/test_script.js +15 -0
- createsonline/static/test_styles.css +59 -0
- createsonline/static_files.py +365 -0
- createsonline/templates/404.html +100 -0
- createsonline/templates/admin_login.html +169 -0
- createsonline/templates/base.html +102 -0
- createsonline/templates/index.html +151 -0
- createsonline/templates.py +205 -0
- createsonline/testing.py +322 -0
- createsonline/utils.py +448 -0
- createsonline/validation/__init__.py +49 -0
- createsonline/validation/fields.py +598 -0
- createsonline/validation/models.py +504 -0
- createsonline/validation/validators.py +561 -0
- createsonline/views.py +184 -0
- createsonline-0.1.26.dist-info/METADATA +46 -0
- createsonline-0.1.26.dist-info/RECORD +152 -0
- createsonline-0.1.26.dist-info/WHEEL +5 -0
- createsonline-0.1.26.dist-info/entry_points.txt +2 -0
- createsonline-0.1.26.dist-info/licenses/LICENSE +21 -0
- createsonline-0.1.26.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,2041 @@
|
|
|
1
|
+
# createsonline/cli/main.py
|
|
2
|
+
"""
|
|
3
|
+
CREATESONLINE Dynamic CLI - Revolutionary Natural Language Interface
|
|
4
|
+
|
|
5
|
+
The world's first AI-native framework CLI that understands natural language.
|
|
6
|
+
No rigid commands - just express your intent naturally!
|
|
7
|
+
|
|
8
|
+
Examples:
|
|
9
|
+
createsonline "create new AI-powered project called myapp"
|
|
10
|
+
createsonline "start development server on port 8000"
|
|
11
|
+
createsonline "show comprehensive framework information"
|
|
12
|
+
createsonline "create superuser admin with full access"
|
|
13
|
+
|
|
14
|
+
Zero external dependencies - pure Python implementation.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
import sys
|
|
19
|
+
import os
|
|
20
|
+
import re
|
|
21
|
+
import subprocess
|
|
22
|
+
import asyncio
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Dict, List, Any, Optional, Tuple
|
|
25
|
+
|
|
26
|
+
# Python 3.9-3.13 support check
|
|
27
|
+
if sys.version_info < (3, 9) or sys.version_info >= (3, 14):
|
|
28
|
+
logging.getLogger("createsonline.cli").error("Unsupported Python version")
|
|
29
|
+
sys.exit(1)
|
|
30
|
+
|
|
31
|
+
# Optional rich imports with internal fallbacks
|
|
32
|
+
try:
|
|
33
|
+
from rich.console import Console
|
|
34
|
+
from rich.panel import Panel
|
|
35
|
+
from rich.table import Table
|
|
36
|
+
from rich.progress import track
|
|
37
|
+
from rich.prompt import Prompt, Confirm
|
|
38
|
+
RICH_AVAILABLE = True
|
|
39
|
+
console = Console()
|
|
40
|
+
except ImportError:
|
|
41
|
+
RICH_AVAILABLE = False
|
|
42
|
+
console = None
|
|
43
|
+
|
|
44
|
+
# Optional typer import with internal fallback
|
|
45
|
+
try:
|
|
46
|
+
import typer
|
|
47
|
+
TYPER_AVAILABLE = True
|
|
48
|
+
except ImportError:
|
|
49
|
+
TYPER_AVAILABLE = False
|
|
50
|
+
# CRITICAL FIX: Create typer stub to prevent crashes
|
|
51
|
+
import types
|
|
52
|
+
typer = types.ModuleType("typer")
|
|
53
|
+
|
|
54
|
+
# Add stub attributes to prevent AttributeError
|
|
55
|
+
def _typer_stub(*args, **kwargs):
|
|
56
|
+
raise RuntimeError("Typer not installed. Install with: pip install typer")
|
|
57
|
+
|
|
58
|
+
typer.Typer = _typer_stub
|
|
59
|
+
typer.Argument = _typer_stub
|
|
60
|
+
typer.Option = _typer_stub
|
|
61
|
+
typer.Context = _typer_stub
|
|
62
|
+
typer.Exit = SystemExit
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class CreatesonlineInternalConsole:
|
|
66
|
+
"""Internal console implementation"""
|
|
67
|
+
|
|
68
|
+
def __init__(self):
|
|
69
|
+
self.width = 80
|
|
70
|
+
|
|
71
|
+
def print(self, text: str, style: str = ""):
|
|
72
|
+
"""Print with optional styling"""
|
|
73
|
+
# Simple color codes for terminals that support them
|
|
74
|
+
colors = {
|
|
75
|
+
"red": "\033[91m",
|
|
76
|
+
"green": "\033[92m",
|
|
77
|
+
"yellow": "\033[93m",
|
|
78
|
+
"blue": "\033[94m",
|
|
79
|
+
"cyan": "\033[96m",
|
|
80
|
+
"white": "\033[97m",
|
|
81
|
+
"bold": "\033[1m",
|
|
82
|
+
"reset": "\033[0m"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if "red" in style:
|
|
86
|
+
print(f"{colors.get('red', '')}{text}{colors.get('reset', '')}")
|
|
87
|
+
elif "green" in style:
|
|
88
|
+
print(f"{colors.get('green', '')}{text}{colors.get('reset', '')}")
|
|
89
|
+
elif "yellow" in style:
|
|
90
|
+
print(f"{colors.get('yellow', '')}{text}{colors.get('reset', '')}")
|
|
91
|
+
elif "blue" in style:
|
|
92
|
+
print(f"{colors.get('blue', '')}{text}{colors.get('reset', '')}")
|
|
93
|
+
elif "cyan" in style:
|
|
94
|
+
print(f"{colors.get('cyan', '')}{text}{colors.get('reset', '')}")
|
|
95
|
+
elif "bold" in style:
|
|
96
|
+
print(f"{colors.get('bold', '')}{text}{colors.get('reset', '')}")
|
|
97
|
+
else:
|
|
98
|
+
print(text)
|
|
99
|
+
|
|
100
|
+
def panel(self, text: str, title: str = "", border_style: str = ""):
|
|
101
|
+
"""Create a simple panel"""
|
|
102
|
+
lines = text.split('\n')
|
|
103
|
+
max_width = max(len(line) for line in lines) if lines else 0
|
|
104
|
+
panel_width = max(max_width + 4, len(title) + 4, 40)
|
|
105
|
+
|
|
106
|
+
# Top border
|
|
107
|
+
if title:
|
|
108
|
+
title_line = f"┌─ {title} " + "─" * (panel_width - len(title) - 4) + "â”"
|
|
109
|
+
else:
|
|
110
|
+
title_line = "┌" + "─" * (panel_width - 2) + "â”"
|
|
111
|
+
|
|
112
|
+
print(title_line)
|
|
113
|
+
|
|
114
|
+
# Content
|
|
115
|
+
for line in lines:
|
|
116
|
+
padded_line = f"│ {line:<{panel_width-4}} │"
|
|
117
|
+
print(padded_line)
|
|
118
|
+
|
|
119
|
+
# Bottom border
|
|
120
|
+
print("└" + "─" * (panel_width - 2) + "┘")
|
|
121
|
+
|
|
122
|
+
def table(self, data: List[List[str]], headers: List[str] = None):
|
|
123
|
+
"""Create a simple table"""
|
|
124
|
+
if not data:
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
# Calculate column widths
|
|
128
|
+
if headers:
|
|
129
|
+
all_rows = [headers] + data
|
|
130
|
+
else:
|
|
131
|
+
all_rows = data
|
|
132
|
+
|
|
133
|
+
col_widths = []
|
|
134
|
+
for col_idx in range(len(all_rows[0])):
|
|
135
|
+
max_width = max(len(str(row[col_idx])) for row in all_rows if col_idx < len(row))
|
|
136
|
+
col_widths.append(max_width + 2)
|
|
137
|
+
|
|
138
|
+
# Print headers
|
|
139
|
+
if headers:
|
|
140
|
+
header_line = "|".join(f" {headers[i]:<{col_widths[i]-1}}" for i in range(len(headers)))
|
|
141
|
+
print(header_line)
|
|
142
|
+
print("-" * len(header_line))
|
|
143
|
+
|
|
144
|
+
# Print data
|
|
145
|
+
for row in data:
|
|
146
|
+
row_line = "|".join(f" {str(row[i]):<{col_widths[i]-1}}" if i < len(row) else f" {'':<{col_widths[i]-1}}" for i in range(len(col_widths)))
|
|
147
|
+
print(row_line)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class CreatesonlineNaturalLanguageCLI:
|
|
151
|
+
"""
|
|
152
|
+
Revolutionary Natural Language CLI for CREATESONLINE
|
|
153
|
+
|
|
154
|
+
Understands user intent through natural language processing
|
|
155
|
+
without external NLP dependencies - pure Python pattern matching.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def __init__(self):
|
|
159
|
+
self.console = console if RICH_AVAILABLE else CreatesonlineInternalConsole()
|
|
160
|
+
self.commands_db = self._build_commands_database()
|
|
161
|
+
self.context = {
|
|
162
|
+
"last_command": None,
|
|
163
|
+
"current_directory": os.getcwd(),
|
|
164
|
+
"framework_version": "0.1.6"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
def _build_commands_database(self) -> Dict[str, Dict[str, Any]]:
|
|
168
|
+
"""Build natural language commands database"""
|
|
169
|
+
return {
|
|
170
|
+
# Project Management
|
|
171
|
+
"create_project": {
|
|
172
|
+
"patterns": [
|
|
173
|
+
r"create\s+(new\s+)?project\s+(called\s+|named\s+)?(\w+)",
|
|
174
|
+
r"new\s+project\s+(\w+)",
|
|
175
|
+
r"make\s+(a\s+)?project\s+(\w+)",
|
|
176
|
+
r"generate\s+project\s+(\w+)",
|
|
177
|
+
r"init\s+project\s+(\w+)"
|
|
178
|
+
],
|
|
179
|
+
"handler": "handle_create_project",
|
|
180
|
+
"description": "Create a new CREATESONLINE project",
|
|
181
|
+
"examples": [
|
|
182
|
+
'create new project called myapp',
|
|
183
|
+
'new project blog',
|
|
184
|
+
'make a project ecommerce'
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
# Project Initialization
|
|
189
|
+
"init_project": {
|
|
190
|
+
"patterns": [
|
|
191
|
+
r"^init(ialize)?\s*$",
|
|
192
|
+
r"^init(ialize)?\s+project\s*$",
|
|
193
|
+
r"^setup\s+project\s*$",
|
|
194
|
+
r"^bootstrap\s+project\s*$"
|
|
195
|
+
],
|
|
196
|
+
"handler": "handle_init_project",
|
|
197
|
+
"description": "Initialize project structure in current directory",
|
|
198
|
+
"examples": [
|
|
199
|
+
'init',
|
|
200
|
+
'initialize project',
|
|
201
|
+
'setup project'
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
# Server Management
|
|
206
|
+
"start_server": {
|
|
207
|
+
"patterns": [
|
|
208
|
+
# FIXED: Added word boundaries and more specific patterns
|
|
209
|
+
r"^start\s+(development|dev)\s+server(\s+on\s+port\s+(\d+))?\b",
|
|
210
|
+
r"^run\s+(dev|development)\s+server(\s+port\s+(\d+))?\b",
|
|
211
|
+
r"^serve\s+dev(elopment)?(\s+on\s+(\d+))?\b",
|
|
212
|
+
r"^dev\s+server(\s+port\s+(\d+))?\b"
|
|
213
|
+
],
|
|
214
|
+
"handler": "handle_start_server",
|
|
215
|
+
"description": "Start development server",
|
|
216
|
+
"examples": [
|
|
217
|
+
'start development server',
|
|
218
|
+
'start server on port 8000',
|
|
219
|
+
'run dev server with hot reload',
|
|
220
|
+
'serve development on port 8080'
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
# Production Server
|
|
225
|
+
"production_server": {
|
|
226
|
+
"patterns": [
|
|
227
|
+
# FIXED: More specific production patterns
|
|
228
|
+
r"^start\s+production\s+server(\s+with\s+(\d+)\s+workers)?\b",
|
|
229
|
+
r"^run\s+prod(uction)?\s+server(\s+(\d+)\s+workers)?\b",
|
|
230
|
+
r"^production\s+mode(\s+(\d+)\s+workers)?\b",
|
|
231
|
+
r"^serve\s+production(\s+(\d+)\s+workers)?\b"
|
|
232
|
+
],
|
|
233
|
+
"handler": "handle_production_server",
|
|
234
|
+
"description": "Start production server",
|
|
235
|
+
"examples": [
|
|
236
|
+
'start production server',
|
|
237
|
+
'run prod server with 4 workers',
|
|
238
|
+
'production mode'
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
# Information Commands
|
|
243
|
+
"framework_info": {
|
|
244
|
+
"patterns": [
|
|
245
|
+
# FIXED: More specific info patterns to avoid conflicts
|
|
246
|
+
r"^show\s+(me\s+)?(framework\s+)?info(rmation)?\b",
|
|
247
|
+
r"^what\s+is\s+createsonline\b",
|
|
248
|
+
r"^framework\s+details\b",
|
|
249
|
+
r"^info\s*$", # Exact match for just "info"
|
|
250
|
+
r"^about\s+(createsonline|framework)\b"
|
|
251
|
+
],
|
|
252
|
+
"handler": "handle_framework_info",
|
|
253
|
+
"description": "Show framework information",
|
|
254
|
+
"examples": [
|
|
255
|
+
'show me framework info',
|
|
256
|
+
'what is createsonline',
|
|
257
|
+
'info'
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
|
|
261
|
+
# Version Information
|
|
262
|
+
"version": {
|
|
263
|
+
"patterns": [
|
|
264
|
+
# FIXED: Exact version patterns to avoid matching "conversion" etc
|
|
265
|
+
r"^version\s*$",
|
|
266
|
+
r"^show\s+version\b",
|
|
267
|
+
r"^what\s+version\b",
|
|
268
|
+
r"^\-\-version\s*$",
|
|
269
|
+
r"^v\s*$" # Just "v" alone
|
|
270
|
+
],
|
|
271
|
+
"handler": "handle_version",
|
|
272
|
+
"description": "Show version information",
|
|
273
|
+
"examples": [
|
|
274
|
+
'version',
|
|
275
|
+
'what version',
|
|
276
|
+
'show version'
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
# User Management
|
|
281
|
+
"create_superuser": {
|
|
282
|
+
"patterns": [
|
|
283
|
+
r"create\s+(super)?user(\s+(called\s+|named\s+)?(\w+))?",
|
|
284
|
+
r"add\s+(super)?user(\s+(\w+))?",
|
|
285
|
+
r"make\s+(super)?user(\s+(\w+))?",
|
|
286
|
+
r"new\s+(super)?user(\s+(\w+))?"
|
|
287
|
+
],
|
|
288
|
+
"handler": "handle_create_superuser",
|
|
289
|
+
"description": "Create admin superuser",
|
|
290
|
+
"examples": [
|
|
291
|
+
'create superuser',
|
|
292
|
+
'add user admin',
|
|
293
|
+
'create superuser called john'
|
|
294
|
+
]
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
# Shell Access
|
|
298
|
+
"shell": {
|
|
299
|
+
"patterns": [
|
|
300
|
+
r"shell",
|
|
301
|
+
r"interactive\s+shell",
|
|
302
|
+
r"python\s+shell",
|
|
303
|
+
r"repl"
|
|
304
|
+
],
|
|
305
|
+
"handler": "handle_shell",
|
|
306
|
+
"description": "Start interactive shell",
|
|
307
|
+
"examples": [
|
|
308
|
+
'shell',
|
|
309
|
+
'interactive shell',
|
|
310
|
+
'python shell'
|
|
311
|
+
]
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
# Help System
|
|
315
|
+
"help": {
|
|
316
|
+
"patterns": [
|
|
317
|
+
r"help",
|
|
318
|
+
r"what\s+can\s+(i|you)\s+do",
|
|
319
|
+
r"commands",
|
|
320
|
+
r"usage",
|
|
321
|
+
r"\?"
|
|
322
|
+
],
|
|
323
|
+
"handler": "handle_help",
|
|
324
|
+
"description": "Show available commands",
|
|
325
|
+
"examples": [
|
|
326
|
+
'help',
|
|
327
|
+
'what can you do',
|
|
328
|
+
'commands'
|
|
329
|
+
]
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
# AI Features
|
|
333
|
+
"ai_Example": {
|
|
334
|
+
"patterns": [
|
|
335
|
+
r"show\s+ai\s+(Example|features|capabilities)",
|
|
336
|
+
r"ai\s+Example",
|
|
337
|
+
r"Examplenstrate\s+ai",
|
|
338
|
+
r"what\s+ai\s+features"
|
|
339
|
+
],
|
|
340
|
+
"handler": "handle_ai_Example",
|
|
341
|
+
"description": "Examplenstrate AI capabilities",
|
|
342
|
+
"examples": [
|
|
343
|
+
'show ai Example',
|
|
344
|
+
'ai features',
|
|
345
|
+
'Examplenstrate ai'
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
|
|
349
|
+
# Database AI Query
|
|
350
|
+
"db_ai_query": {
|
|
351
|
+
"patterns": [
|
|
352
|
+
r"db\s+ai-query\s+(.+)",
|
|
353
|
+
r"database\s+query\s+(.+)",
|
|
354
|
+
r"ai\s+query\s+(.+)",
|
|
355
|
+
r"query\s+database\s+(.+)"
|
|
356
|
+
],
|
|
357
|
+
"handler": "handle_db_ai_query",
|
|
358
|
+
"description": "Query database using natural language",
|
|
359
|
+
"examples": [
|
|
360
|
+
'db ai-query "show last 10 users"',
|
|
361
|
+
'database query "count all sessions"',
|
|
362
|
+
'ai query "show errors"'
|
|
363
|
+
]
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
# Database Rollback
|
|
367
|
+
"db_rollback": {
|
|
368
|
+
"patterns": [
|
|
369
|
+
r"db\s+rollback(\s+(\d+))?",
|
|
370
|
+
r"database\s+rollback(\s+(\d+))?",
|
|
371
|
+
r"rollback\s+database(\s+(\d+))?"
|
|
372
|
+
],
|
|
373
|
+
"handler": "handle_db_rollback",
|
|
374
|
+
"description": "Rollback database operations",
|
|
375
|
+
"examples": [
|
|
376
|
+
'db rollback',
|
|
377
|
+
'database rollback 5',
|
|
378
|
+
'rollback last 3 operations'
|
|
379
|
+
]
|
|
380
|
+
},
|
|
381
|
+
|
|
382
|
+
# Database Audit Log
|
|
383
|
+
"db_audit_log": {
|
|
384
|
+
"patterns": [
|
|
385
|
+
r"db\s+audit-log(\s+(\d+))?",
|
|
386
|
+
r"database\s+audit(\s+(\d+))?",
|
|
387
|
+
r"show\s+audit\s+log(\s+(\d+))?",
|
|
388
|
+
r"audit\s+trail(\s+(\d+))?"
|
|
389
|
+
],
|
|
390
|
+
"handler": "handle_db_audit_log",
|
|
391
|
+
"description": "Show database audit log",
|
|
392
|
+
"examples": [
|
|
393
|
+
'db audit-log',
|
|
394
|
+
'database audit 10',
|
|
395
|
+
'show audit log'
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
def parse_natural_language(self, input_text: str) -> Tuple[Optional[str], Dict[str, Any]]:
|
|
401
|
+
"""
|
|
402
|
+
Parse natural language input and extract intent + parameters
|
|
403
|
+
|
|
404
|
+
Returns:
|
|
405
|
+
(command_name, parameters_dict)
|
|
406
|
+
"""
|
|
407
|
+
input_text = input_text.lower().strip()
|
|
408
|
+
|
|
409
|
+
for command_name, command_data in self.commands_db.items():
|
|
410
|
+
for pattern in command_data["patterns"]:
|
|
411
|
+
match = re.search(pattern, input_text)
|
|
412
|
+
if match:
|
|
413
|
+
# Extract parameters from regex groups
|
|
414
|
+
params = self._extract_parameters(command_name, match, input_text)
|
|
415
|
+
return command_name, params
|
|
416
|
+
|
|
417
|
+
return None, {}
|
|
418
|
+
|
|
419
|
+
def _extract_parameters(self, command_name: str, match: re.Match, full_text: str) -> Dict[str, Any]:
|
|
420
|
+
"""Extract parameters from regex match - FIXED: Improved stop-word filtering"""
|
|
421
|
+
params = {}
|
|
422
|
+
groups = match.groups()
|
|
423
|
+
|
|
424
|
+
# FIXED: Better stop words list with more specific filtering
|
|
425
|
+
STOP_WORDS = {
|
|
426
|
+
'a', 'an', 'the', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with',
|
|
427
|
+
'new', 'called', 'named', 'create', 'start', 'make', 'run', 'launch', 'serve',
|
|
428
|
+
'super', 'admin', 'user', 'project', 'server', 'app', 'application'
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if command_name == "create_project":
|
|
432
|
+
# Extract project name - FIXED: Better filtering
|
|
433
|
+
for group in groups:
|
|
434
|
+
if group and group.strip():
|
|
435
|
+
clean_name = group.strip().lower()
|
|
436
|
+
# FIXED: More strict validation - avoid common words
|
|
437
|
+
if (clean_name not in STOP_WORDS and
|
|
438
|
+
len(clean_name) > 2 and # Must be longer than 2 chars
|
|
439
|
+
not clean_name.isdigit() and # Not just numbers
|
|
440
|
+
clean_name.replace('_', '').replace('-', '').isalnum()): # Valid identifier chars
|
|
441
|
+
params['project_name'] = group.strip()
|
|
442
|
+
break
|
|
443
|
+
|
|
444
|
+
# Default fallback if no valid name found
|
|
445
|
+
if 'project_name' not in params:
|
|
446
|
+
params['project_name'] = 'my_project'
|
|
447
|
+
|
|
448
|
+
# Check for AI features
|
|
449
|
+
if 'ai' in full_text or 'artificial intelligence' in full_text:
|
|
450
|
+
params['ai_features'] = True
|
|
451
|
+
if 'admin' in full_text:
|
|
452
|
+
params['admin_enabled'] = True
|
|
453
|
+
if 'auth' in full_text or 'authentication' in full_text:
|
|
454
|
+
params['auth_enabled'] = True
|
|
455
|
+
|
|
456
|
+
elif command_name in ["start_server", "production_server"]:
|
|
457
|
+
# Extract port number
|
|
458
|
+
for group in groups:
|
|
459
|
+
if group and group.isdigit():
|
|
460
|
+
port_num = int(group)
|
|
461
|
+
# FIXED: Validate reasonable port range
|
|
462
|
+
if 1000 <= port_num <= 65535:
|
|
463
|
+
params['port'] = port_num
|
|
464
|
+
break
|
|
465
|
+
|
|
466
|
+
# FIXED: Better worker extraction for production
|
|
467
|
+
if command_name == "production_server":
|
|
468
|
+
# Look for explicit worker mentions, not just any number
|
|
469
|
+
for group in groups:
|
|
470
|
+
if group and group.isdigit():
|
|
471
|
+
worker_count = int(group)
|
|
472
|
+
if 1 <= worker_count <= 16: # Reasonable worker range
|
|
473
|
+
params['workers'] = worker_count
|
|
474
|
+
break
|
|
475
|
+
|
|
476
|
+
elif command_name == "db_ai_query":
|
|
477
|
+
# Extract the natural language query
|
|
478
|
+
for group in groups:
|
|
479
|
+
if group and group.strip():
|
|
480
|
+
# Clean up quotes and whitespace
|
|
481
|
+
query = group.strip().strip('"\'')
|
|
482
|
+
if query:
|
|
483
|
+
params['query'] = query
|
|
484
|
+
break
|
|
485
|
+
|
|
486
|
+
elif command_name == "db_rollback":
|
|
487
|
+
# Extract count for rollback
|
|
488
|
+
for group in groups:
|
|
489
|
+
if group and group.isdigit():
|
|
490
|
+
count = int(group)
|
|
491
|
+
if 1 <= count <= 100: # Reasonable limit
|
|
492
|
+
params['count'] = count
|
|
493
|
+
break
|
|
494
|
+
if 'count' not in params:
|
|
495
|
+
params['count'] = 1 # Default rollback count
|
|
496
|
+
|
|
497
|
+
elif command_name == "db_audit_log":
|
|
498
|
+
# Extract limit for audit log
|
|
499
|
+
for group in groups:
|
|
500
|
+
if group and group.isdigit():
|
|
501
|
+
limit = int(group)
|
|
502
|
+
if 1 <= limit <= 1000: # Reasonable limit
|
|
503
|
+
params['limit'] = limit
|
|
504
|
+
break
|
|
505
|
+
if 'limit' not in params:
|
|
506
|
+
params['limit'] = 10 # Default limit
|
|
507
|
+
if re.search(r'(\d+)\s*workers?', full_text, re.IGNORECASE):
|
|
508
|
+
worker_match = re.search(r'(\d+)\s*workers?', full_text, re.IGNORECASE)
|
|
509
|
+
if worker_match:
|
|
510
|
+
params['workers'] = int(worker_match.group(1))
|
|
511
|
+
else:
|
|
512
|
+
params['workers'] = 4 # Reasonable default for production
|
|
513
|
+
|
|
514
|
+
elif command_name == "create_superuser":
|
|
515
|
+
# Extract username - FIXED: Better validation
|
|
516
|
+
for group in groups:
|
|
517
|
+
if group and group.strip():
|
|
518
|
+
clean_username = group.strip().lower()
|
|
519
|
+
if (clean_username not in STOP_WORDS and
|
|
520
|
+
len(clean_username) >= 3 and
|
|
521
|
+
clean_username.replace('_', '').isalnum()):
|
|
522
|
+
params['username'] = group.strip()
|
|
523
|
+
break
|
|
524
|
+
|
|
525
|
+
# Default fallback
|
|
526
|
+
if 'username' not in params:
|
|
527
|
+
params['username'] = 'admin'
|
|
528
|
+
|
|
529
|
+
return params
|
|
530
|
+
|
|
531
|
+
async def execute_command(self, command_name: str, params: Dict[str, Any]) -> bool:
|
|
532
|
+
"""Execute the parsed command"""
|
|
533
|
+
|
|
534
|
+
if command_name not in self.commands_db:
|
|
535
|
+
return False
|
|
536
|
+
|
|
537
|
+
handler_name = self.commands_db[command_name]["handler"]
|
|
538
|
+
handler = getattr(self, handler_name, None)
|
|
539
|
+
|
|
540
|
+
if handler:
|
|
541
|
+
try:
|
|
542
|
+
await handler(params)
|
|
543
|
+
self.context["last_command"] = command_name
|
|
544
|
+
return True
|
|
545
|
+
except Exception as e:
|
|
546
|
+
self._error(f"Command execution failed: {e}")
|
|
547
|
+
return False
|
|
548
|
+
|
|
549
|
+
return False
|
|
550
|
+
|
|
551
|
+
# ========================================
|
|
552
|
+
# COMMAND HANDLERS
|
|
553
|
+
# ========================================
|
|
554
|
+
|
|
555
|
+
async def handle_create_project(self, params: Dict[str, Any]):
|
|
556
|
+
"""Handle project creation with natural language parameters"""
|
|
557
|
+
project_name = params.get('project_name', 'my_createsonline_app')
|
|
558
|
+
ai_features = params.get('ai_features', True) # Default to True for AI-native framework
|
|
559
|
+
admin_enabled = params.get('admin_enabled', True)
|
|
560
|
+
auth_enabled = params.get('auth_enabled', True)
|
|
561
|
+
|
|
562
|
+
self._info(f"Creating CREATESONLINE project: {project_name}")
|
|
563
|
+
|
|
564
|
+
# Show project configuration
|
|
565
|
+
config_data = [
|
|
566
|
+
["Feature", "Status"],
|
|
567
|
+
["AI Features", "✅ Enabled" if ai_features else "⌠Disabled"],
|
|
568
|
+
["Admin Interface", "✅ Enabled" if admin_enabled else "⌠Disabled"],
|
|
569
|
+
["Authentication", "✅ Enabled" if auth_enabled else "⌠Disabled"]
|
|
570
|
+
]
|
|
571
|
+
|
|
572
|
+
if RICH_AVAILABLE:
|
|
573
|
+
table = Table(title="Project Configuration")
|
|
574
|
+
table.add_column("Feature", style="cyan")
|
|
575
|
+
table.add_column("Status", style="green")
|
|
576
|
+
for row in config_data[1:]:
|
|
577
|
+
table.add_row(row[0], row[1])
|
|
578
|
+
console.print(table)
|
|
579
|
+
else:
|
|
580
|
+
self.console.table(config_data[1:], config_data[0])
|
|
581
|
+
|
|
582
|
+
# Create project structure
|
|
583
|
+
await self._create_project_structure(project_name, ai_features, admin_enabled, auth_enabled)
|
|
584
|
+
|
|
585
|
+
# Show next steps
|
|
586
|
+
self._success(f"Project '{project_name}' created successfully!")
|
|
587
|
+
self._info("Next steps:")
|
|
588
|
+
self._info(f"1. cd {project_name}")
|
|
589
|
+
self._info("2. python -m venv venv")
|
|
590
|
+
self._info("3. source venv/bin/activate # Windows: venv\\Scripts\\activate")
|
|
591
|
+
self._info("4. pip install -r requirements.txt")
|
|
592
|
+
self._info("5. createsonline 'start development server'")
|
|
593
|
+
|
|
594
|
+
async def handle_init_project(self, params: Dict[str, Any]):
|
|
595
|
+
"""Initialize project structure in current directory"""
|
|
596
|
+
try:
|
|
597
|
+
from createsonline.project_init import ProjectInitializer
|
|
598
|
+
|
|
599
|
+
self._info("Initializing CREATESONLINE project structure...")
|
|
600
|
+
|
|
601
|
+
# Get current directory
|
|
602
|
+
project_root = Path.cwd()
|
|
603
|
+
self._info(f"Project root: {project_root}")
|
|
604
|
+
|
|
605
|
+
# Initialize project with verbose output for CLI
|
|
606
|
+
initializer = ProjectInitializer(project_root)
|
|
607
|
+
result = initializer.initialize(verbose=True)
|
|
608
|
+
|
|
609
|
+
# Show results
|
|
610
|
+
if result.get("success"):
|
|
611
|
+
created_files = result.get("created_files", [])
|
|
612
|
+
skipped_files = result.get("user_files_skipped", [])
|
|
613
|
+
created_dirs = result.get("created_directories", [])
|
|
614
|
+
|
|
615
|
+
# Show created directories
|
|
616
|
+
for dir_path in created_dirs:
|
|
617
|
+
self._info(f" Created directory: {dir_path}")
|
|
618
|
+
|
|
619
|
+
# Show created files
|
|
620
|
+
for file_info in created_files:
|
|
621
|
+
self._info(f" Created {file_info['type']}: {file_info['path']}")
|
|
622
|
+
|
|
623
|
+
# Show skipped files (user customizations)
|
|
624
|
+
if skipped_files:
|
|
625
|
+
self._warning(f"\nSkipped {len(skipped_files)} existing file(s) to preserve your customizations:")
|
|
626
|
+
for filepath in skipped_files:
|
|
627
|
+
self._info(f" * {filepath}")
|
|
628
|
+
|
|
629
|
+
self._success(f"\nInitialization complete!")
|
|
630
|
+
self._info(f"Created {len(created_files)} new files")
|
|
631
|
+
|
|
632
|
+
if skipped_files:
|
|
633
|
+
self._info(f"Protected {len(skipped_files)} existing files")
|
|
634
|
+
|
|
635
|
+
# Show next steps
|
|
636
|
+
self._info("\nNext steps:")
|
|
637
|
+
self._info(" 1. Edit routes.py to add your custom routes")
|
|
638
|
+
self._info(" 2. Customize templates/ and static/ folders")
|
|
639
|
+
self._info(" 3. Run: python main.py")
|
|
640
|
+
self._success("\nHappy coding!")
|
|
641
|
+
|
|
642
|
+
else:
|
|
643
|
+
self._error("Initialization failed")
|
|
644
|
+
error_msg = result.get("error", "Unknown error")
|
|
645
|
+
self._error(f"Error: {error_msg}")
|
|
646
|
+
|
|
647
|
+
except ImportError:
|
|
648
|
+
self._error("ProjectInitializer not found. Please upgrade createsonline:")
|
|
649
|
+
self._info(" pip install --upgrade createsonline")
|
|
650
|
+
except Exception as e:
|
|
651
|
+
self._error(f"Initialization failed: {e}")
|
|
652
|
+
import traceback
|
|
653
|
+
self._error(traceback.format_exc())
|
|
654
|
+
|
|
655
|
+
async def handle_start_server(self, params: Dict[str, Any]):
|
|
656
|
+
"""Handle development server startup"""
|
|
657
|
+
port = params.get('port', 8000)
|
|
658
|
+
host = params.get('host', '0.0.0.0')
|
|
659
|
+
|
|
660
|
+
# Check for application files
|
|
661
|
+
app_files = ["main.py", "app.py"]
|
|
662
|
+
app_file = None
|
|
663
|
+
|
|
664
|
+
for file in app_files:
|
|
665
|
+
if Path(file).exists():
|
|
666
|
+
app_file = file
|
|
667
|
+
break
|
|
668
|
+
|
|
669
|
+
if not app_file:
|
|
670
|
+
await self._create_basic_app()
|
|
671
|
+
app_file = "main.py"
|
|
672
|
+
|
|
673
|
+
try:
|
|
674
|
+
# Pass port and host as environment variables
|
|
675
|
+
env = os.environ.copy()
|
|
676
|
+
env['PORT'] = str(port)
|
|
677
|
+
env['HOST'] = host
|
|
678
|
+
|
|
679
|
+
# Use internal pure Python server - no uvicorn needed!
|
|
680
|
+
subprocess.run([
|
|
681
|
+
sys.executable, app_file
|
|
682
|
+
], env=env)
|
|
683
|
+
except KeyboardInterrupt:
|
|
684
|
+
pass
|
|
685
|
+
except Exception as e:
|
|
686
|
+
self._error(f"Error: {e}")
|
|
687
|
+
|
|
688
|
+
async def handle_production_server(self, params: Dict[str, Any]):
|
|
689
|
+
"""Handle production server startup"""
|
|
690
|
+
port = params.get('port', 8000)
|
|
691
|
+
workers = params.get('workers', 4)
|
|
692
|
+
|
|
693
|
+
self._info(f"Starting CREATESONLINE production server with {workers} workers")
|
|
694
|
+
|
|
695
|
+
# Production configuration
|
|
696
|
+
self._panel_info("Production Server", f"""
|
|
697
|
+
ðŸ CREATESONLINE Production Mode
|
|
698
|
+
âš¡ Workers: {workers}
|
|
699
|
+
🌠Port: {port}
|
|
700
|
+
🔒 Security: Enabled
|
|
701
|
+
📊 Monitoring: Active
|
|
702
|
+
""")
|
|
703
|
+
|
|
704
|
+
try:
|
|
705
|
+
# Use internal pure Python server - production mode
|
|
706
|
+
# Note: For true multi-worker support, consider using gunicorn with the internal server
|
|
707
|
+
subprocess.run([
|
|
708
|
+
sys.executable, "main.py"
|
|
709
|
+
])
|
|
710
|
+
except Exception as e:
|
|
711
|
+
self._error(f"Production server failed: {e}")
|
|
712
|
+
|
|
713
|
+
async def handle_framework_info(self, params: Dict[str, Any]):
|
|
714
|
+
"""Show comprehensive framework information"""
|
|
715
|
+
|
|
716
|
+
# Framework banner
|
|
717
|
+
banner = """
|
|
718
|
+
â•”â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•—
|
|
719
|
+
â•‘ CREATESONLINE â•‘
|
|
720
|
+
â•‘ The AI-Native Web Framework â•‘
|
|
721
|
+
â•‘ â•‘
|
|
722
|
+
â•‘ Build Intelligence Into Everything â•‘
|
|
723
|
+
â•‘ â•‘
|
|
724
|
+
â•‘ Version: 0.1.0 | Python: 3.9-3.13 â•‘
|
|
725
|
+
â•‘ Pure Framework | AI-First | Pure Python â•‘
|
|
726
|
+
╚â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
|
|
727
|
+
""".strip()
|
|
728
|
+
|
|
729
|
+
self._info(banner)
|
|
730
|
+
|
|
731
|
+
# Features table
|
|
732
|
+
features_data = [
|
|
733
|
+
["Feature", "Status", "Description"],
|
|
734
|
+
["AI-Native Core", "✅ Active", "Built-in AI capabilities"],
|
|
735
|
+
["Pure Python", "✅ Active", "Works with just Python"],
|
|
736
|
+
["Dynamic CLI", "✅ Active", "Natural language commands"],
|
|
737
|
+
["Admin Interface", "✅ Ready", "Built-in admin panel"],
|
|
738
|
+
["User Management", "✅ Ready", "Built-in authentication"],
|
|
739
|
+
["Vector Search", "✅ Ready", "Semantic similarity"],
|
|
740
|
+
["LLM Integration", "🔄 Optional", "When API keys provided"],
|
|
741
|
+
["Auto Templates", "✅ Active", "Internal template system"]
|
|
742
|
+
]
|
|
743
|
+
|
|
744
|
+
if RICH_AVAILABLE:
|
|
745
|
+
table = Table(title="Framework Features")
|
|
746
|
+
table.add_column("Feature", style="cyan")
|
|
747
|
+
table.add_column("Status", style="green")
|
|
748
|
+
table.add_column("Description", style="white")
|
|
749
|
+
for row in features_data[1:]:
|
|
750
|
+
table.add_row(row[0], row[1], row[2])
|
|
751
|
+
console.print(table)
|
|
752
|
+
else:
|
|
753
|
+
self.console.table(features_data[1:], features_data[0])
|
|
754
|
+
|
|
755
|
+
# Natural language examples
|
|
756
|
+
self._panel_info("Natural Language CLI Examples", """
|
|
757
|
+
• "create new AI-powered project called blog"
|
|
758
|
+
• "start development server on port 8000"
|
|
759
|
+
• "launch production server with 4 workers"
|
|
760
|
+
• "create superuser admin with full permissions"
|
|
761
|
+
• "show available AI capabilities and features"
|
|
762
|
+
• "start server in development mode"
|
|
763
|
+
• "display framework information and status"
|
|
764
|
+
""")
|
|
765
|
+
|
|
766
|
+
async def handle_version(self, params: Dict[str, Any]):
|
|
767
|
+
"""Show version information"""
|
|
768
|
+
|
|
769
|
+
# Reference to our logo files
|
|
770
|
+
logo_path = os.path.join(os.path.dirname(__file__), "..", "static", "image")
|
|
771
|
+
favicon_files = ["favicon.svg", "favicon.ico", "logo.png"]
|
|
772
|
+
|
|
773
|
+
version_info = f"""
|
|
774
|
+
C⎯◠CREATESONLINE Framework v0.1.0 - Ultimate Pure Independence
|
|
775
|
+
|
|
776
|
+
ðŸ Python: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}
|
|
777
|
+
ðŸ–¥ï¸ Platform: {sys.platform}
|
|
778
|
+
📠Location: {os.path.dirname(__file__)}
|
|
779
|
+
🎯 Mode: {'Enhanced' if RICH_AVAILABLE else 'Core'}
|
|
780
|
+
🎨 Brand Assets: {logo_path}
|
|
781
|
+
|
|
782
|
+
Build Intelligence Into Everything
|
|
783
|
+
""".strip()
|
|
784
|
+
|
|
785
|
+
self._panel_info("Version Information", version_info)
|
|
786
|
+
|
|
787
|
+
async def handle_create_superuser(self, params: Dict[str, Any]):
|
|
788
|
+
"""Handle superuser creation"""
|
|
789
|
+
username = params.get('username', 'admin')
|
|
790
|
+
|
|
791
|
+
self._info(f"Creating superuser: {username}")
|
|
792
|
+
|
|
793
|
+
# In a real implementation, this would create the user
|
|
794
|
+
# For now, show what would happen
|
|
795
|
+
self._panel_info("Superuser Creation", f"""
|
|
796
|
+
👤 Username: {username}
|
|
797
|
+
🔑 Password: [Interactive prompt would appear]
|
|
798
|
+
ðŸ›¡ï¸ Permissions: Full admin access
|
|
799
|
+
📧 Email: [Would be requested]
|
|
800
|
+
""")
|
|
801
|
+
|
|
802
|
+
self._success(f"Superuser '{username}' would be created!")
|
|
803
|
+
self._info("This feature requires the full CREATESONLINE installation.")
|
|
804
|
+
|
|
805
|
+
async def handle_shell(self, params: Dict[str, Any]):
|
|
806
|
+
"""Start interactive shell"""
|
|
807
|
+
self._info("Starting CREATESONLINE interactive shell...")
|
|
808
|
+
|
|
809
|
+
try:
|
|
810
|
+
# Try to start Python shell with CREATESONLINE imports
|
|
811
|
+
code = '''
|
|
812
|
+
import sys
|
|
813
|
+
sys.path.insert(0, ".")
|
|
814
|
+
|
|
815
|
+
# Try to import CREATESONLINE
|
|
816
|
+
try:
|
|
817
|
+
import createsonline
|
|
818
|
+
print("✅ CREATESONLINE imported successfully")
|
|
819
|
+
print("Available: createsonline.create_app()")
|
|
820
|
+
except ImportError:
|
|
821
|
+
print("âš ï¸ CREATESONLINE not in Python path")
|
|
822
|
+
|
|
823
|
+
print("🚠CREATESONLINE Interactive Shell")
|
|
824
|
+
logging.getLogger("createsonline.cli").info("Type exit() to quit")
|
|
825
|
+
'''
|
|
826
|
+
|
|
827
|
+
# Start Python with the code
|
|
828
|
+
subprocess.run([sys.executable, "-i", "-c", code])
|
|
829
|
+
|
|
830
|
+
except KeyboardInterrupt:
|
|
831
|
+
self._info("Shell session ended")
|
|
832
|
+
|
|
833
|
+
async def handle_help(self, params: Dict[str, Any]):
|
|
834
|
+
"""Show help information"""
|
|
835
|
+
|
|
836
|
+
self._panel_info("C⎯◠CREATESONLINE Natural Language CLI", """
|
|
837
|
+
🎯 Express your intent naturally - no rigid commands needed!
|
|
838
|
+
|
|
839
|
+
Examples of what you can say:
|
|
840
|
+
""")
|
|
841
|
+
|
|
842
|
+
# Group commands by category
|
|
843
|
+
categories = {
|
|
844
|
+
"Project Management": ["create_project"],
|
|
845
|
+
"Server Operations": ["start_server", "production_server"],
|
|
846
|
+
"User Management": ["create_superuser"],
|
|
847
|
+
"Information": ["framework_info", "version", "help"],
|
|
848
|
+
"Development": ["shell", "ai_Example"]
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
for category, command_names in categories.items():
|
|
852
|
+
self._info(f"\n📂 {category}:")
|
|
853
|
+
for cmd_name in command_names:
|
|
854
|
+
if cmd_name in self.commands_db:
|
|
855
|
+
examples = self.commands_db[cmd_name]["examples"]
|
|
856
|
+
for example in examples[:2]: # Show first 2 examples
|
|
857
|
+
self._info(f" • createsonline \"{example}\"")
|
|
858
|
+
|
|
859
|
+
async def handle_ai_Example(self, params: Dict[str, Any]):
|
|
860
|
+
"""Examplenstrate AI capabilities"""
|
|
861
|
+
|
|
862
|
+
self._panel_info("CREATESONLINE AI Capabilities", """
|
|
863
|
+
🧠Built-in AI Features:
|
|
864
|
+
|
|
865
|
+
• Hash-based Embeddings - Consistent vector representations
|
|
866
|
+
• Rule-based Generation - Smart text creation
|
|
867
|
+
• Similarity Search - Find related content
|
|
868
|
+
• AI Field Types - Database fields with intelligence
|
|
869
|
+
• Mock AI Services - Development-ready AI
|
|
870
|
+
|
|
871
|
+
🔥 Enhanced AI (With API Keys):
|
|
872
|
+
|
|
873
|
+
• OpenAI Integration - GPT models for generation
|
|
874
|
+
• Anthropic Claude - Advanced reasoning
|
|
875
|
+
• Vector Databases - Production embeddings
|
|
876
|
+
• Real-time Learning - Adaptive algorithms
|
|
877
|
+
""")
|
|
878
|
+
|
|
879
|
+
# Show AI field examples
|
|
880
|
+
self._info("\n🎯 AI Field Examples:")
|
|
881
|
+
self._info(" • AIComputedField - Automatic ML predictions")
|
|
882
|
+
self._info(" • LLMField - Content generation")
|
|
883
|
+
self._info(" • VectorField - Semantic search")
|
|
884
|
+
self._info(" • SmartTextField - Text analysis")
|
|
885
|
+
|
|
886
|
+
async def handle_db_ai_query(self, params: Dict[str, Any]):
|
|
887
|
+
"""Handle database AI query command"""
|
|
888
|
+
query = params.get('query', '')
|
|
889
|
+
if not query:
|
|
890
|
+
self._error("No query provided. Usage: db ai-query 'show last 10 users'")
|
|
891
|
+
return
|
|
892
|
+
|
|
893
|
+
try:
|
|
894
|
+
# Import the database AI query command
|
|
895
|
+
from createsonline.cli.commands.database import db_ai_query_command
|
|
896
|
+
db_ai_query_command(query) # Remove await - function is not async
|
|
897
|
+
except ImportError as e:
|
|
898
|
+
self._error(f"Database commands not available: {e}")
|
|
899
|
+
except Exception as e:
|
|
900
|
+
self._error(f"Query failed: {e}")
|
|
901
|
+
|
|
902
|
+
async def handle_db_rollback(self, params: Dict[str, Any]):
|
|
903
|
+
"""Handle database rollback command"""
|
|
904
|
+
count = params.get('count', 1)
|
|
905
|
+
|
|
906
|
+
try:
|
|
907
|
+
# Import the database rollback command
|
|
908
|
+
from createsonline.cli.commands.database import db_rollback_command
|
|
909
|
+
db_rollback_command(count) # Remove await - function is not async
|
|
910
|
+
except ImportError as e:
|
|
911
|
+
self._error(f"Database commands not available: {e}")
|
|
912
|
+
except Exception as e:
|
|
913
|
+
self._error(f"Rollback failed: {e}")
|
|
914
|
+
|
|
915
|
+
async def handle_db_audit_log(self, params: Dict[str, Any]):
|
|
916
|
+
"""Handle database audit log command"""
|
|
917
|
+
limit = params.get('limit', 10)
|
|
918
|
+
|
|
919
|
+
try:
|
|
920
|
+
# Import the database audit log command
|
|
921
|
+
from createsonline.cli.commands.database import db_audit_log_command
|
|
922
|
+
db_audit_log_command(limit) # Remove await - function is not async
|
|
923
|
+
except ImportError as e:
|
|
924
|
+
self._error(f"Database commands not available: {e}")
|
|
925
|
+
except Exception as e:
|
|
926
|
+
self._error(f"Audit log failed: {e}")
|
|
927
|
+
|
|
928
|
+
try:
|
|
929
|
+
# Import the database audit log command
|
|
930
|
+
from createsonline.cli.commands.database import db_audit_log_command
|
|
931
|
+
await db_audit_log_command(limit)
|
|
932
|
+
except ImportError as e:
|
|
933
|
+
self._error(f"Database commands not available: {e}")
|
|
934
|
+
except Exception as e:
|
|
935
|
+
self._error(f"Audit log failed: {e}")
|
|
936
|
+
|
|
937
|
+
# ========================================
|
|
938
|
+
# UTILITY METHODS
|
|
939
|
+
# ========================================
|
|
940
|
+
|
|
941
|
+
def _info(self, message: str):
|
|
942
|
+
"""Print info message"""
|
|
943
|
+
if RICH_AVAILABLE:
|
|
944
|
+
console.print(message, style="blue")
|
|
945
|
+
else:
|
|
946
|
+
self.console.print(message, "blue")
|
|
947
|
+
|
|
948
|
+
def _success(self, message: str):
|
|
949
|
+
"""Print success message"""
|
|
950
|
+
if RICH_AVAILABLE:
|
|
951
|
+
console.print(f"✅ {message}", style="green")
|
|
952
|
+
else:
|
|
953
|
+
self.console.print(f"✅ {message}", "green")
|
|
954
|
+
|
|
955
|
+
def _warning(self, message: str):
|
|
956
|
+
"""Print warning message"""
|
|
957
|
+
if RICH_AVAILABLE:
|
|
958
|
+
console.print(f"âš ï¸ {message}", style="yellow")
|
|
959
|
+
else:
|
|
960
|
+
self.console.print(f"âš ï¸ {message}", "yellow")
|
|
961
|
+
|
|
962
|
+
def _error(self, message: str):
|
|
963
|
+
"""Print error message"""
|
|
964
|
+
if RICH_AVAILABLE:
|
|
965
|
+
console.print(f"⌠{message}", style="red")
|
|
966
|
+
else:
|
|
967
|
+
self.console.print(f"⌠{message}", "red")
|
|
968
|
+
|
|
969
|
+
def _panel_info(self, title: str, content: str):
|
|
970
|
+
"""Print panel with info"""
|
|
971
|
+
if RICH_AVAILABLE:
|
|
972
|
+
console.print(Panel(content.strip(), title=title, border_style="blue"))
|
|
973
|
+
else:
|
|
974
|
+
self.console.panel(content.strip(), title)
|
|
975
|
+
|
|
976
|
+
async def _create_project_structure(self, project_name: str, ai_features: bool, admin_enabled: bool, auth_enabled: bool):
|
|
977
|
+
"""Create project directory structure"""
|
|
978
|
+
|
|
979
|
+
project_path = Path(project_name)
|
|
980
|
+
if project_path.exists():
|
|
981
|
+
self._warning(f"Directory '{project_name}' already exists")
|
|
982
|
+
return
|
|
983
|
+
|
|
984
|
+
# Create directories
|
|
985
|
+
project_path.mkdir()
|
|
986
|
+
(project_path / "static").mkdir()
|
|
987
|
+
(project_path / "templates").mkdir()
|
|
988
|
+
(project_path / "tests").mkdir()
|
|
989
|
+
|
|
990
|
+
# Generate main.py
|
|
991
|
+
main_content = self._generate_main_py(project_name, ai_features, admin_enabled, auth_enabled)
|
|
992
|
+
(project_path / "main.py").write_text(main_content)
|
|
993
|
+
|
|
994
|
+
# Generate requirements.txt - Pure CREATESONLINE, no external server needed!
|
|
995
|
+
requirements = "createsonline>=0.1.0"
|
|
996
|
+
if ai_features:
|
|
997
|
+
requirements += "\n# AI Features (optional)\n# openai>=1.0.0\n# numpy>=1.24.0"
|
|
998
|
+
(project_path / "requirements.txt").write_text(requirements)
|
|
999
|
+
|
|
1000
|
+
# Generate .env
|
|
1001
|
+
env_content = f"""# {project_name} Configuration
|
|
1002
|
+
DEBUG=true
|
|
1003
|
+
SECRET_KEY=your-secret-key-change-in-production
|
|
1004
|
+
DATABASE_URL=sqlite:///./app.db
|
|
1005
|
+
HOST=127.0.0.1
|
|
1006
|
+
PORT=8000
|
|
1007
|
+
|
|
1008
|
+
# AI Configuration (optional)
|
|
1009
|
+
# OPENAI_API_KEY=your-key-here
|
|
1010
|
+
"""
|
|
1011
|
+
(project_path / ".env").write_text(env_content)
|
|
1012
|
+
|
|
1013
|
+
# Generate README.md
|
|
1014
|
+
readme_content = f"""# {project_name}
|
|
1015
|
+
|
|
1016
|
+
Built with **CREATESONLINE** - The AI-Native Web Framework
|
|
1017
|
+
|
|
1018
|
+
## Quick Start
|
|
1019
|
+
|
|
1020
|
+
```bash
|
|
1021
|
+
# Install dependencies
|
|
1022
|
+
pip install -r requirements.txt
|
|
1023
|
+
|
|
1024
|
+
# Start development server
|
|
1025
|
+
createsonline "start development server"
|
|
1026
|
+
|
|
1027
|
+
# Or traditionally
|
|
1028
|
+
python main.py
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
## Natural Language CLI
|
|
1032
|
+
|
|
1033
|
+
```bash
|
|
1034
|
+
createsonline "show comprehensive framework information"
|
|
1035
|
+
createsonline "create superuser admin with full permissions"
|
|
1036
|
+
createsonline "start development server on port 8000"
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
Built with Intelligence Into Everything C⎯â—
|
|
1040
|
+
"""
|
|
1041
|
+
(project_path / "README.md").write_text(readme_content)
|
|
1042
|
+
|
|
1043
|
+
def _generate_main_py(self, project_name: str, ai_features: bool, admin_enabled: bool, auth_enabled: bool) -> str:
|
|
1044
|
+
"""Generate main.py content"""
|
|
1045
|
+
|
|
1046
|
+
ai_config = {}
|
|
1047
|
+
if ai_features:
|
|
1048
|
+
ai_config = {
|
|
1049
|
+
"enable_smart_fields": True,
|
|
1050
|
+
"default_llm": "internal"
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
return f'''#!/usr/bin/env python3
|
|
1054
|
+
"""
|
|
1055
|
+
{project_name} - CREATESONLINE Application
|
|
1056
|
+
|
|
1057
|
+
Built with CREATESONLINE - The AI-Native Web Framework
|
|
1058
|
+
Created with natural language: "create project {project_name}"
|
|
1059
|
+
"""
|
|
1060
|
+
from createsonline import create_app
|
|
1061
|
+
|
|
1062
|
+
# Create CREATESONLINE application
|
|
1063
|
+
app = create_app(
|
|
1064
|
+
title="{project_name.title()}",
|
|
1065
|
+
description="AI-powered application built with CREATESONLINE",
|
|
1066
|
+
version="1.0.0",
|
|
1067
|
+
ai_config={ai_config},
|
|
1068
|
+
debug=False
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
{f"# Enable AI features\\napp.enable_ai_features(['smart_query', 'content_generation', 'vector_search'])" if ai_features else ""}
|
|
1072
|
+
|
|
1073
|
+
@app.get("/")
|
|
1074
|
+
async def home(request):
|
|
1075
|
+
"""Home page"""
|
|
1076
|
+
return {{
|
|
1077
|
+
"message": "Welcome to {project_name.title()}!",
|
|
1078
|
+
"framework": "CREATESONLINE",
|
|
1079
|
+
"ai_enabled": {str(ai_features).lower()},
|
|
1080
|
+
"admin_enabled": {str(admin_enabled).lower()},
|
|
1081
|
+
"auth_enabled": {str(auth_enabled).lower()},
|
|
1082
|
+
"status": "operational"
|
|
1083
|
+
}}
|
|
1084
|
+
|
|
1085
|
+
@app.get("/api/status")
|
|
1086
|
+
async def api_status(request):
|
|
1087
|
+
"""API status"""
|
|
1088
|
+
return {{
|
|
1089
|
+
"service": "{project_name.title()} API",
|
|
1090
|
+
"status": "operational",
|
|
1091
|
+
"framework": "CREATESONLINE",
|
|
1092
|
+
"version": "1.0.0"
|
|
1093
|
+
}}
|
|
1094
|
+
|
|
1095
|
+
@app.get("/health")
|
|
1096
|
+
async def health(request):
|
|
1097
|
+
"""Health check"""
|
|
1098
|
+
return {{"status": "healthy", "framework": "CREATESONLINE"}}
|
|
1099
|
+
|
|
1100
|
+
@app.get("/createsonline.spec.json")
|
|
1101
|
+
async def createsonline_spec(request):
|
|
1102
|
+
"""CREATESONLINE API Specification - Pure Internal Implementation"""
|
|
1103
|
+
from datetime import datetime
|
|
1104
|
+
import platform
|
|
1105
|
+
import sys
|
|
1106
|
+
|
|
1107
|
+
return {{
|
|
1108
|
+
"createsonline": "0.1.0", # Framework version
|
|
1109
|
+
"spec_version": "1.0.0", # Spec format version
|
|
1110
|
+
"compatible_with": ["openapi-3.0"], # Compatible formats (for tools)
|
|
1111
|
+
"info": {{
|
|
1112
|
+
"title": "CREATESONLINE Framework API",
|
|
1113
|
+
"description": "AI-Native Web Framework - Complete API Specification",
|
|
1114
|
+
"version": "1.0.0",
|
|
1115
|
+
"framework": "CREATESONLINE",
|
|
1116
|
+
"framework_version": "0.1.0",
|
|
1117
|
+
"framework_type": "AI-Native",
|
|
1118
|
+
"spec_format": "createsonline-spec-v1"
|
|
1119
|
+
}},
|
|
1120
|
+
"servers": [
|
|
1121
|
+
{{
|
|
1122
|
+
"url": "/",
|
|
1123
|
+
"description": "CREATESONLINE Internal Pure Python Server",
|
|
1124
|
+
"x-server-type": "internal-asgi"
|
|
1125
|
+
}}
|
|
1126
|
+
],
|
|
1127
|
+
"paths": {{
|
|
1128
|
+
"/": {{
|
|
1129
|
+
"get": {{
|
|
1130
|
+
"summary": "Home Page",
|
|
1131
|
+
"tags": ["CREATESONLINE-Core"],
|
|
1132
|
+
"responses": {{
|
|
1133
|
+
"200": {{
|
|
1134
|
+
"description": "Home page with framework information"
|
|
1135
|
+
}}
|
|
1136
|
+
}}
|
|
1137
|
+
}}
|
|
1138
|
+
}},
|
|
1139
|
+
"/health": {{
|
|
1140
|
+
"get": {{
|
|
1141
|
+
"summary": "Health Check",
|
|
1142
|
+
"tags": ["CREATESONLINE-Core"],
|
|
1143
|
+
"responses": {{
|
|
1144
|
+
"200": {{
|
|
1145
|
+
"description": "Service health status",
|
|
1146
|
+
"content": {{
|
|
1147
|
+
"application/json": {{
|
|
1148
|
+
"schema": {{
|
|
1149
|
+
"type": "object",
|
|
1150
|
+
"properties": {{
|
|
1151
|
+
"status": {{"type": "string"}},
|
|
1152
|
+
"framework": {{"type": "string"}}
|
|
1153
|
+
}}
|
|
1154
|
+
}}
|
|
1155
|
+
}}
|
|
1156
|
+
}}
|
|
1157
|
+
}}
|
|
1158
|
+
}}
|
|
1159
|
+
}}
|
|
1160
|
+
}},
|
|
1161
|
+
"/api/status": {{
|
|
1162
|
+
"get": {{
|
|
1163
|
+
"summary": "API Status",
|
|
1164
|
+
"tags": ["CREATESONLINE-Core"],
|
|
1165
|
+
"responses": {{
|
|
1166
|
+
"200": {{
|
|
1167
|
+
"description": "API operational status"
|
|
1168
|
+
}}
|
|
1169
|
+
}}
|
|
1170
|
+
}}
|
|
1171
|
+
}},
|
|
1172
|
+
"/createsonline.spec.json": {{
|
|
1173
|
+
"get": {{
|
|
1174
|
+
"summary": "CREATESONLINE API Specification",
|
|
1175
|
+
"tags": ["CREATESONLINE-Core"],
|
|
1176
|
+
"responses": {{
|
|
1177
|
+
"200": {{
|
|
1178
|
+
"description": "Complete API specification in CREATESONLINE format"
|
|
1179
|
+
}}
|
|
1180
|
+
}}
|
|
1181
|
+
}}
|
|
1182
|
+
}}
|
|
1183
|
+
}},
|
|
1184
|
+
"tags": [
|
|
1185
|
+
{{
|
|
1186
|
+
"name": "CREATESONLINE-Core",
|
|
1187
|
+
"description": "Core framework endpoints"
|
|
1188
|
+
}}
|
|
1189
|
+
]
|
|
1190
|
+
}}
|
|
1191
|
+
|
|
1192
|
+
if __name__ == "__main__":
|
|
1193
|
+
import os
|
|
1194
|
+
from createsonline.server import run_server
|
|
1195
|
+
|
|
1196
|
+
# Load environment variables from .env file
|
|
1197
|
+
try:
|
|
1198
|
+
from dotenv import load_dotenv
|
|
1199
|
+
load_dotenv()
|
|
1200
|
+
except ImportError:
|
|
1201
|
+
pass
|
|
1202
|
+
|
|
1203
|
+
host = os.getenv("HOST", "127.0.0.1")
|
|
1204
|
+
port = int(os.getenv("PORT", "8000"))
|
|
1205
|
+
|
|
1206
|
+
run_server(app, host=host, port=port)
|
|
1207
|
+
'''
|
|
1208
|
+
|
|
1209
|
+
async def _create_basic_app(self):
|
|
1210
|
+
"""Create basic application file if none exists or update if outdated"""
|
|
1211
|
+
|
|
1212
|
+
TEMPLATE_VERSION = "0.1.1"
|
|
1213
|
+
|
|
1214
|
+
# Check if main.py exists and has version marker
|
|
1215
|
+
if Path("main.py").exists():
|
|
1216
|
+
content = Path("main.py").read_text(encoding='utf-8')
|
|
1217
|
+
# Check if it's our auto-generated template
|
|
1218
|
+
if "Auto-generated by CREATESONLINE CLI" in content:
|
|
1219
|
+
# Extract version from existing file
|
|
1220
|
+
import re
|
|
1221
|
+
version_match = re.search(r'Template Version: ([\d.]+)', content)
|
|
1222
|
+
if version_match:
|
|
1223
|
+
existing_version = version_match.group(1)
|
|
1224
|
+
if existing_version == TEMPLATE_VERSION:
|
|
1225
|
+
# Already up to date, don't regenerate
|
|
1226
|
+
return
|
|
1227
|
+
else:
|
|
1228
|
+
self._info(f"Updating main.py from v{existing_version} to v{TEMPLATE_VERSION}")
|
|
1229
|
+
else:
|
|
1230
|
+
# Old template without version, update it
|
|
1231
|
+
self._info("Updating main.py to latest template")
|
|
1232
|
+
else:
|
|
1233
|
+
# User's custom main.py, don't touch it
|
|
1234
|
+
return
|
|
1235
|
+
|
|
1236
|
+
# Build template with version header
|
|
1237
|
+
version_header = f'''#!/usr/bin/env python3
|
|
1238
|
+
"""
|
|
1239
|
+
Basic CREATESONLINE Application
|
|
1240
|
+
|
|
1241
|
+
Auto-generated by CREATESONLINE CLI
|
|
1242
|
+
Template Version: {TEMPLATE_VERSION}
|
|
1243
|
+
"""
|
|
1244
|
+
'''
|
|
1245
|
+
|
|
1246
|
+
basic_app = version_header + '''from createsonline import create_app
|
|
1247
|
+
|
|
1248
|
+
# Create basic CREATESONLINE application
|
|
1249
|
+
app = create_app(
|
|
1250
|
+
title="CREATESONLINE Example",
|
|
1251
|
+
description="Basic CREATESONLINE application",
|
|
1252
|
+
version="1.0.0",
|
|
1253
|
+
debug=False
|
|
1254
|
+
)
|
|
1255
|
+
|
|
1256
|
+
@app.get("/")
|
|
1257
|
+
async def home(request):
|
|
1258
|
+
"""Home page with beautiful UI"""
|
|
1259
|
+
html = """
|
|
1260
|
+
<!DOCTYPE html>
|
|
1261
|
+
<html lang="en">
|
|
1262
|
+
<head>
|
|
1263
|
+
<meta charset="UTF-8">
|
|
1264
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1265
|
+
<title>CREATESONLINE Framework</title>
|
|
1266
|
+
|
|
1267
|
+
<!-- Favicons -->
|
|
1268
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
1269
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/icons/icon-32x32.png">
|
|
1270
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/icons/icon-16x16.png">
|
|
1271
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/icons/icon-180x180.png">
|
|
1272
|
+
<link rel="manifest" href="/site.webmanifest">
|
|
1273
|
+
|
|
1274
|
+
<style>
|
|
1275
|
+
* {
|
|
1276
|
+
margin: 0;
|
|
1277
|
+
padding: 0;
|
|
1278
|
+
box-sizing: border-box;
|
|
1279
|
+
}}
|
|
1280
|
+
|
|
1281
|
+
body {{
|
|
1282
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
1283
|
+
background: linear-gradient(135deg, #000000 0%, #1a1a1a 50%, #000000 100%);
|
|
1284
|
+
min-height: 100vh;
|
|
1285
|
+
display: flex;
|
|
1286
|
+
justify-content: center;
|
|
1287
|
+
align-items: center;
|
|
1288
|
+
padding: 20px;
|
|
1289
|
+
position: relative;
|
|
1290
|
+
overflow: hidden;
|
|
1291
|
+
}}
|
|
1292
|
+
|
|
1293
|
+
body::before {{
|
|
1294
|
+
content: '';
|
|
1295
|
+
position: absolute;
|
|
1296
|
+
top: -50%;
|
|
1297
|
+
left: -50%;
|
|
1298
|
+
width: 200%;
|
|
1299
|
+
height: 200%;
|
|
1300
|
+
background: repeating-linear-gradient(
|
|
1301
|
+
0deg,
|
|
1302
|
+
transparent,
|
|
1303
|
+
transparent 2px,
|
|
1304
|
+
rgba(255, 255, 255, 0.03) 2px,
|
|
1305
|
+
rgba(255, 255, 255, 0.03) 4px
|
|
1306
|
+
);
|
|
1307
|
+
animation: scan 8s linear infinite;
|
|
1308
|
+
pointer-events: none;
|
|
1309
|
+
}}
|
|
1310
|
+
|
|
1311
|
+
@keyframes scan {{
|
|
1312
|
+
0% {{ transform: translateY(0); }}
|
|
1313
|
+
100% {{ transform: translateY(50px); }}
|
|
1314
|
+
}}
|
|
1315
|
+
|
|
1316
|
+
.container {{
|
|
1317
|
+
background: rgba(255, 255, 255, 0.98);
|
|
1318
|
+
backdrop-filter: blur(10px);
|
|
1319
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
1320
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
1321
|
+
padding: 80px 60px;
|
|
1322
|
+
max-width: 1000px;
|
|
1323
|
+
width: 100%;
|
|
1324
|
+
animation: slideUp 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1325
|
+
position: relative;
|
|
1326
|
+
z-index: 1;
|
|
1327
|
+
}}
|
|
1328
|
+
|
|
1329
|
+
@keyframes slideUp {{
|
|
1330
|
+
from {{
|
|
1331
|
+
opacity: 0;
|
|
1332
|
+
transform: translateY(30px);
|
|
1333
|
+
}}
|
|
1334
|
+
to {{
|
|
1335
|
+
opacity: 1;
|
|
1336
|
+
transform: translateY(0);
|
|
1337
|
+
}}
|
|
1338
|
+
}}
|
|
1339
|
+
|
|
1340
|
+
.logo {{
|
|
1341
|
+
display: block;
|
|
1342
|
+
margin: 0 auto 50px;
|
|
1343
|
+
max-width: 280px;
|
|
1344
|
+
width: 100%;
|
|
1345
|
+
height: auto;
|
|
1346
|
+
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1));
|
|
1347
|
+
}}
|
|
1348
|
+
|
|
1349
|
+
h1 {{
|
|
1350
|
+
font-size: 2.8em;
|
|
1351
|
+
color: #000000;
|
|
1352
|
+
margin-bottom: 15px;
|
|
1353
|
+
text-align: center;
|
|
1354
|
+
font-weight: 300;
|
|
1355
|
+
letter-spacing: -1px;
|
|
1356
|
+
position: relative;
|
|
1357
|
+
}}
|
|
1358
|
+
|
|
1359
|
+
h1::after {{
|
|
1360
|
+
content: '';
|
|
1361
|
+
display: block;
|
|
1362
|
+
width: 60px;
|
|
1363
|
+
height: 3px;
|
|
1364
|
+
background: #000000;
|
|
1365
|
+
margin: 20px auto 0;
|
|
1366
|
+
}}
|
|
1367
|
+
|
|
1368
|
+
.subtitle {{
|
|
1369
|
+
text-align: center;
|
|
1370
|
+
color: #666666;
|
|
1371
|
+
font-size: 1.1em;
|
|
1372
|
+
margin-bottom: 50px;
|
|
1373
|
+
font-weight: 300;
|
|
1374
|
+
line-height: 1.6;
|
|
1375
|
+
}}
|
|
1376
|
+
|
|
1377
|
+
.links {{
|
|
1378
|
+
display: grid;
|
|
1379
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1380
|
+
gap: 25px;
|
|
1381
|
+
margin: 50px 0;
|
|
1382
|
+
}}
|
|
1383
|
+
|
|
1384
|
+
.link-card {{
|
|
1385
|
+
background: #000000;
|
|
1386
|
+
padding: 40px 30px;
|
|
1387
|
+
text-decoration: none;
|
|
1388
|
+
color: white;
|
|
1389
|
+
transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1390
|
+
border: 2px solid #000000;
|
|
1391
|
+
position: relative;
|
|
1392
|
+
overflow: hidden;
|
|
1393
|
+
}}
|
|
1394
|
+
|
|
1395
|
+
.link-card::before {{
|
|
1396
|
+
content: '';
|
|
1397
|
+
position: absolute;
|
|
1398
|
+
top: 0;
|
|
1399
|
+
left: -100%;
|
|
1400
|
+
width: 100%;
|
|
1401
|
+
height: 100%;
|
|
1402
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
|
1403
|
+
transition: left 0.5s;
|
|
1404
|
+
}}
|
|
1405
|
+
|
|
1406
|
+
.link-card:hover::before {{
|
|
1407
|
+
left: 100%;
|
|
1408
|
+
}}
|
|
1409
|
+
|
|
1410
|
+
.link-card:hover {{
|
|
1411
|
+
background: #ffffff;
|
|
1412
|
+
color: #000000;
|
|
1413
|
+
border: 2px solid #000000;
|
|
1414
|
+
transform: translateY(-8px);
|
|
1415
|
+
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.3);
|
|
1416
|
+
}}
|
|
1417
|
+
|
|
1418
|
+
.link-card h3 {{
|
|
1419
|
+
margin-bottom: 12px;
|
|
1420
|
+
font-size: 1.3em;
|
|
1421
|
+
font-weight: 600;
|
|
1422
|
+
letter-spacing: -0.5px;
|
|
1423
|
+
}}
|
|
1424
|
+
|
|
1425
|
+
.link-card p {{
|
|
1426
|
+
opacity: 0.85;
|
|
1427
|
+
font-size: 0.95em;
|
|
1428
|
+
font-weight: 300;
|
|
1429
|
+
line-height: 1.6;
|
|
1430
|
+
}}
|
|
1431
|
+
|
|
1432
|
+
.link-card:hover p {{
|
|
1433
|
+
opacity: 0.7;
|
|
1434
|
+
}}
|
|
1435
|
+
|
|
1436
|
+
.version {{
|
|
1437
|
+
text-align: center;
|
|
1438
|
+
color: #999999;
|
|
1439
|
+
margin-top: 60px;
|
|
1440
|
+
font-size: 0.85em;
|
|
1441
|
+
font-weight: 300;
|
|
1442
|
+
padding-top: 40px;
|
|
1443
|
+
border-top: 1px solid #e0e0e0;
|
|
1444
|
+
}}
|
|
1445
|
+
|
|
1446
|
+
.version p {{
|
|
1447
|
+
margin: 5px 0;
|
|
1448
|
+
}}
|
|
1449
|
+
|
|
1450
|
+
@media (max-width: 768px) {{
|
|
1451
|
+
.links {{
|
|
1452
|
+
grid-template-columns: 1fr;
|
|
1453
|
+
}}
|
|
1454
|
+
|
|
1455
|
+
.container {{
|
|
1456
|
+
padding: 50px 30px;
|
|
1457
|
+
}}
|
|
1458
|
+
|
|
1459
|
+
h1 {{
|
|
1460
|
+
font-size: 2em;
|
|
1461
|
+
}}
|
|
1462
|
+
}}
|
|
1463
|
+
</style>
|
|
1464
|
+
</head>
|
|
1465
|
+
<body>
|
|
1466
|
+
<div class="container">
|
|
1467
|
+
<img src="/logo-header-h200@2x.png" alt="CREATESONLINE" class="logo">
|
|
1468
|
+
<h1>AI-Native Web Framework</h1>
|
|
1469
|
+
|
|
1470
|
+
<div class="links">
|
|
1471
|
+
<a href="https://createsonline.com/docs" class="link-card">
|
|
1472
|
+
<h3>Documentation</h3>
|
|
1473
|
+
<p>Complete guides and API reference</p>
|
|
1474
|
+
</a>
|
|
1475
|
+
|
|
1476
|
+
<a href="https://createsonline.com/guide" class="link-card">
|
|
1477
|
+
<h3>Quick Start</h3>
|
|
1478
|
+
<p>Get started in 5 minutes</p>
|
|
1479
|
+
</a>
|
|
1480
|
+
|
|
1481
|
+
<a href="https://createsonline.com/examples" class="link-card">
|
|
1482
|
+
<h3>Examples</h3>
|
|
1483
|
+
<p>Real-world code examples</p>
|
|
1484
|
+
</a>
|
|
1485
|
+
|
|
1486
|
+
<a href="https://github.com/meahmedh/createsonline" class="link-card">
|
|
1487
|
+
<h3>GitHub</h3>
|
|
1488
|
+
<p>View source and contribute</p>
|
|
1489
|
+
</a>
|
|
1490
|
+
</div>
|
|
1491
|
+
|
|
1492
|
+
<div class="version">
|
|
1493
|
+
<p>CREATESONLINE v0.1.0</p>
|
|
1494
|
+
<p>Built by the CREATESONLINE Team</p>
|
|
1495
|
+
</div>
|
|
1496
|
+
</div>
|
|
1497
|
+
</body>
|
|
1498
|
+
</html>
|
|
1499
|
+
"""
|
|
1500
|
+
|
|
1501
|
+
# Return HTML directly as string
|
|
1502
|
+
return html
|
|
1503
|
+
|
|
1504
|
+
@app.get("/admin")
|
|
1505
|
+
async def admin_login(request):
|
|
1506
|
+
"""Admin login page"""
|
|
1507
|
+
html = """
|
|
1508
|
+
<!DOCTYPE html>
|
|
1509
|
+
<html lang="en">
|
|
1510
|
+
<head>
|
|
1511
|
+
<meta charset="UTF-8">
|
|
1512
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1513
|
+
<title>Admin Login - CREATESONLINE</title>
|
|
1514
|
+
|
|
1515
|
+
<!-- Favicons -->
|
|
1516
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
|
1517
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/icons/icon-32x32.png">
|
|
1518
|
+
|
|
1519
|
+
<style>
|
|
1520
|
+
* {{
|
|
1521
|
+
margin: 0;
|
|
1522
|
+
padding: 0;
|
|
1523
|
+
box-sizing: border-box;
|
|
1524
|
+
}}
|
|
1525
|
+
|
|
1526
|
+
body {{
|
|
1527
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
1528
|
+
background: linear-gradient(135deg, #000000 0%, #1a1a1a 50%, #000000 100%);
|
|
1529
|
+
min-height: 100vh;
|
|
1530
|
+
display: flex;
|
|
1531
|
+
justify-content: center;
|
|
1532
|
+
align-items: center;
|
|
1533
|
+
padding: 20px;
|
|
1534
|
+
position: relative;
|
|
1535
|
+
overflow: hidden;
|
|
1536
|
+
}}
|
|
1537
|
+
|
|
1538
|
+
body::before {{
|
|
1539
|
+
content: '';
|
|
1540
|
+
position: absolute;
|
|
1541
|
+
top: -50%;
|
|
1542
|
+
left: -50%;
|
|
1543
|
+
width: 200%;
|
|
1544
|
+
height: 200%;
|
|
1545
|
+
background: repeating-linear-gradient(
|
|
1546
|
+
0deg,
|
|
1547
|
+
transparent,
|
|
1548
|
+
transparent 2px,
|
|
1549
|
+
rgba(255, 255, 255, 0.03) 2px,
|
|
1550
|
+
rgba(255, 255, 255, 0.03) 4px
|
|
1551
|
+
);
|
|
1552
|
+
animation: scan 8s linear infinite;
|
|
1553
|
+
pointer-events: none;
|
|
1554
|
+
}}
|
|
1555
|
+
|
|
1556
|
+
@keyframes scan {{
|
|
1557
|
+
0% {{ transform: translateY(0); }}
|
|
1558
|
+
100% {{ transform: translateY(50px); }}
|
|
1559
|
+
}}
|
|
1560
|
+
|
|
1561
|
+
.login-container {{
|
|
1562
|
+
background: rgba(255, 255, 255, 0.98);
|
|
1563
|
+
backdrop-filter: blur(10px);
|
|
1564
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
1565
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
1566
|
+
padding: 60px 50px;
|
|
1567
|
+
max-width: 480px;
|
|
1568
|
+
width: 100%;
|
|
1569
|
+
animation: slideUp 0.8s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1570
|
+
position: relative;
|
|
1571
|
+
z-index: 1;
|
|
1572
|
+
}}
|
|
1573
|
+
|
|
1574
|
+
@keyframes slideUp {{
|
|
1575
|
+
from {{
|
|
1576
|
+
opacity: 0;
|
|
1577
|
+
transform: translateY(30px);
|
|
1578
|
+
}}
|
|
1579
|
+
to {{
|
|
1580
|
+
opacity: 1;
|
|
1581
|
+
transform: translateY(0);
|
|
1582
|
+
}}
|
|
1583
|
+
}}
|
|
1584
|
+
|
|
1585
|
+
.logo {{
|
|
1586
|
+
display: block;
|
|
1587
|
+
margin: 0 auto 40px;
|
|
1588
|
+
max-width: 280px;
|
|
1589
|
+
width: 100%;
|
|
1590
|
+
height: auto;
|
|
1591
|
+
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1));
|
|
1592
|
+
}}
|
|
1593
|
+
|
|
1594
|
+
h1 {{
|
|
1595
|
+
font-size: 2em;
|
|
1596
|
+
color: #000000;
|
|
1597
|
+
margin-bottom: 10px;
|
|
1598
|
+
text-align: center;
|
|
1599
|
+
font-weight: 300;
|
|
1600
|
+
letter-spacing: -0.5px;
|
|
1601
|
+
}}
|
|
1602
|
+
|
|
1603
|
+
h1::after {{
|
|
1604
|
+
content: '';
|
|
1605
|
+
display: block;
|
|
1606
|
+
width: 40px;
|
|
1607
|
+
height: 2px;
|
|
1608
|
+
background: #000000;
|
|
1609
|
+
margin: 15px auto 0;
|
|
1610
|
+
}}
|
|
1611
|
+
|
|
1612
|
+
.subtitle {{
|
|
1613
|
+
text-align: center;
|
|
1614
|
+
color: #666666;
|
|
1615
|
+
font-size: 0.95em;
|
|
1616
|
+
margin-bottom: 45px;
|
|
1617
|
+
font-weight: 300;
|
|
1618
|
+
line-height: 1.6;
|
|
1619
|
+
}}
|
|
1620
|
+
|
|
1621
|
+
.form-group {{
|
|
1622
|
+
margin-bottom: 30px;
|
|
1623
|
+
position: relative;
|
|
1624
|
+
}}
|
|
1625
|
+
|
|
1626
|
+
label {{
|
|
1627
|
+
display: block;
|
|
1628
|
+
color: #000000;
|
|
1629
|
+
font-size: 0.85em;
|
|
1630
|
+
margin-bottom: 10px;
|
|
1631
|
+
font-weight: 600;
|
|
1632
|
+
text-transform: uppercase;
|
|
1633
|
+
letter-spacing: 1px;
|
|
1634
|
+
}}
|
|
1635
|
+
|
|
1636
|
+
input[type="text"],
|
|
1637
|
+
input[type="password"] {{
|
|
1638
|
+
width: 100%;
|
|
1639
|
+
padding: 15px 18px;
|
|
1640
|
+
border: 2px solid #e0e0e0;
|
|
1641
|
+
background: #ffffff;
|
|
1642
|
+
font-size: 1em;
|
|
1643
|
+
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1644
|
+
font-family: inherit;
|
|
1645
|
+
color: #000000;
|
|
1646
|
+
}}
|
|
1647
|
+
|
|
1648
|
+
input[type="text"]:focus,
|
|
1649
|
+
input[type="password"]:focus {{
|
|
1650
|
+
outline: none;
|
|
1651
|
+
background: #fafafa;
|
|
1652
|
+
border-color: #000000;
|
|
1653
|
+
transform: translateY(-2px);
|
|
1654
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
1655
|
+
}}
|
|
1656
|
+
|
|
1657
|
+
button {{
|
|
1658
|
+
width: 100%;
|
|
1659
|
+
padding: 18px;
|
|
1660
|
+
background: #000000;
|
|
1661
|
+
color: white;
|
|
1662
|
+
border: 2px solid #000000;
|
|
1663
|
+
font-size: 1em;
|
|
1664
|
+
font-weight: 600;
|
|
1665
|
+
cursor: pointer;
|
|
1666
|
+
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
1667
|
+
text-transform: uppercase;
|
|
1668
|
+
letter-spacing: 1.5px;
|
|
1669
|
+
font-family: inherit;
|
|
1670
|
+
margin-top: 10px;
|
|
1671
|
+
position: relative;
|
|
1672
|
+
overflow: hidden;
|
|
1673
|
+
}}
|
|
1674
|
+
|
|
1675
|
+
button::before {{
|
|
1676
|
+
content: '';
|
|
1677
|
+
position: absolute;
|
|
1678
|
+
top: 0;
|
|
1679
|
+
left: -100%;
|
|
1680
|
+
width: 100%;
|
|
1681
|
+
height: 100%;
|
|
1682
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
|
1683
|
+
transition: left 0.5s;
|
|
1684
|
+
}}
|
|
1685
|
+
|
|
1686
|
+
button:hover::before {{
|
|
1687
|
+
left: 100%;
|
|
1688
|
+
}}
|
|
1689
|
+
|
|
1690
|
+
button:hover {{
|
|
1691
|
+
background: #ffffff;
|
|
1692
|
+
color: #000000;
|
|
1693
|
+
transform: translateY(-2px);
|
|
1694
|
+
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
|
|
1695
|
+
}}
|
|
1696
|
+
|
|
1697
|
+
button:active {{
|
|
1698
|
+
transform: translateY(0);
|
|
1699
|
+
}}
|
|
1700
|
+
|
|
1701
|
+
.back-link {{
|
|
1702
|
+
text-align: center;
|
|
1703
|
+
margin-top: 35px;
|
|
1704
|
+
padding-top: 30px;
|
|
1705
|
+
border-top: 1px solid #e0e0e0;
|
|
1706
|
+
}}
|
|
1707
|
+
|
|
1708
|
+
.back-link a {{
|
|
1709
|
+
color: #666666;
|
|
1710
|
+
text-decoration: none;
|
|
1711
|
+
font-size: 0.9em;
|
|
1712
|
+
transition: all 0.3s ease;
|
|
1713
|
+
font-weight: 300;
|
|
1714
|
+
}}
|
|
1715
|
+
|
|
1716
|
+
.back-link a:hover {{
|
|
1717
|
+
color: #000000;
|
|
1718
|
+
}}
|
|
1719
|
+
|
|
1720
|
+
@media (max-width: 480px) {{
|
|
1721
|
+
.login-container {{
|
|
1722
|
+
padding: 40px 30px;
|
|
1723
|
+
}}
|
|
1724
|
+
|
|
1725
|
+
h1 {{
|
|
1726
|
+
font-size: 1.6em;
|
|
1727
|
+
}}
|
|
1728
|
+
}}
|
|
1729
|
+
</style>
|
|
1730
|
+
</head>
|
|
1731
|
+
<body>
|
|
1732
|
+
<div class="login-container">
|
|
1733
|
+
<img src="/logo-header-h200@2x.png" alt="CREATESONLINE" class="logo">
|
|
1734
|
+
<h1>Admin Login</h1>
|
|
1735
|
+
<p class="subtitle">Enter your credentials to access the admin panel</p>
|
|
1736
|
+
|
|
1737
|
+
<form method="POST" action="/admin/login">
|
|
1738
|
+
<div class="form-group">
|
|
1739
|
+
<label for="username">Username</label>
|
|
1740
|
+
<input type="text" id="username" name="username" required>
|
|
1741
|
+
</div>
|
|
1742
|
+
|
|
1743
|
+
<div class="form-group">
|
|
1744
|
+
<label for="password">Password</label>
|
|
1745
|
+
<input type="password" id="password" name="password" required>
|
|
1746
|
+
</div>
|
|
1747
|
+
|
|
1748
|
+
<button type="submit">Sign In</button>
|
|
1749
|
+
</form>
|
|
1750
|
+
|
|
1751
|
+
<div class="back-link">
|
|
1752
|
+
<a href="/">Back to Home</a>
|
|
1753
|
+
</div>
|
|
1754
|
+
</div>
|
|
1755
|
+
</body>
|
|
1756
|
+
</html>
|
|
1757
|
+
"""
|
|
1758
|
+
return html
|
|
1759
|
+
|
|
1760
|
+
if __name__ == "__main__":
|
|
1761
|
+
import os
|
|
1762
|
+
from createsonline.server import run_server
|
|
1763
|
+
|
|
1764
|
+
# Load environment variables from .env file
|
|
1765
|
+
try:
|
|
1766
|
+
from dotenv import load_dotenv
|
|
1767
|
+
load_dotenv()
|
|
1768
|
+
except ImportError:
|
|
1769
|
+
pass
|
|
1770
|
+
|
|
1771
|
+
host = os.getenv("HOST", "127.0.0.1")
|
|
1772
|
+
port = int(os.getenv("PORT", "8000"))
|
|
1773
|
+
|
|
1774
|
+
run_server(app, host=host, port=port)
|
|
1775
|
+
'''
|
|
1776
|
+
|
|
1777
|
+
Path("main.py").write_text(basic_app, encoding='utf-8')
|
|
1778
|
+
self._success("Created basic main.py application file")
|
|
1779
|
+
|
|
1780
|
+
|
|
1781
|
+
# ========================================
|
|
1782
|
+
# MAIN CLI ENTRY POINTS
|
|
1783
|
+
# ========================================
|
|
1784
|
+
|
|
1785
|
+
async def main():
|
|
1786
|
+
"""Main CLI entry point - handles natural language input"""
|
|
1787
|
+
|
|
1788
|
+
# Initialize CLI
|
|
1789
|
+
cli = CreatesonlineNaturalLanguageCLI()
|
|
1790
|
+
|
|
1791
|
+
# Handle command line arguments
|
|
1792
|
+
if len(sys.argv) == 1:
|
|
1793
|
+
# No arguments - show help
|
|
1794
|
+
await cli.handle_help({})
|
|
1795
|
+
return
|
|
1796
|
+
|
|
1797
|
+
# Join all arguments as natural language input
|
|
1798
|
+
user_input = " ".join(sys.argv[1:])
|
|
1799
|
+
|
|
1800
|
+
# Handle traditional CLI commands first
|
|
1801
|
+
first_arg = sys.argv[1].lower() if len(sys.argv) > 1 else ""
|
|
1802
|
+
|
|
1803
|
+
if first_arg == "serve":
|
|
1804
|
+
# Traditional serve command
|
|
1805
|
+
port = 8000
|
|
1806
|
+
if len(sys.argv) > 2 and sys.argv[2].isdigit():
|
|
1807
|
+
port = int(sys.argv[2])
|
|
1808
|
+
await cli.handle_start_server({"port": port})
|
|
1809
|
+
return
|
|
1810
|
+
|
|
1811
|
+
if first_arg == "dev":
|
|
1812
|
+
# Traditional dev command
|
|
1813
|
+
port = 8000
|
|
1814
|
+
if len(sys.argv) > 2 and sys.argv[2].isdigit():
|
|
1815
|
+
port = int(sys.argv[2])
|
|
1816
|
+
await cli.handle_start_server({"port": port})
|
|
1817
|
+
return
|
|
1818
|
+
|
|
1819
|
+
if first_arg == "prod":
|
|
1820
|
+
# Traditional production command
|
|
1821
|
+
workers = 4
|
|
1822
|
+
if len(sys.argv) > 2 and sys.argv[2].isdigit():
|
|
1823
|
+
workers = int(sys.argv[2])
|
|
1824
|
+
await cli.handle_production_server({"workers": workers})
|
|
1825
|
+
return
|
|
1826
|
+
|
|
1827
|
+
if first_arg == "new":
|
|
1828
|
+
# Traditional new project command
|
|
1829
|
+
project_name = sys.argv[2] if len(sys.argv) > 2 else "myproject"
|
|
1830
|
+
await cli.handle_create_project({"name": project_name})
|
|
1831
|
+
return
|
|
1832
|
+
|
|
1833
|
+
if first_arg == "init":
|
|
1834
|
+
# Initialize project structure
|
|
1835
|
+
await cli.handle_init_project({})
|
|
1836
|
+
return
|
|
1837
|
+
|
|
1838
|
+
if first_arg == "createsuperuser":
|
|
1839
|
+
# Traditional superuser command
|
|
1840
|
+
await cli.handle_create_superuser({})
|
|
1841
|
+
return
|
|
1842
|
+
|
|
1843
|
+
if first_arg == "shell":
|
|
1844
|
+
# Traditional shell command
|
|
1845
|
+
await cli.handle_shell({})
|
|
1846
|
+
return
|
|
1847
|
+
|
|
1848
|
+
# Handle special cases
|
|
1849
|
+
if user_input in ["--help", "-h", "help"]:
|
|
1850
|
+
await cli.handle_help({})
|
|
1851
|
+
return
|
|
1852
|
+
|
|
1853
|
+
if user_input in ["--version", "-v", "version"]:
|
|
1854
|
+
await cli.handle_version({})
|
|
1855
|
+
return
|
|
1856
|
+
|
|
1857
|
+
# Parse natural language
|
|
1858
|
+
command_name, params = cli.parse_natural_language(user_input)
|
|
1859
|
+
|
|
1860
|
+
if command_name:
|
|
1861
|
+
# Execute parsed command
|
|
1862
|
+
success = await cli.execute_command(command_name, params)
|
|
1863
|
+
|
|
1864
|
+
if success:
|
|
1865
|
+
cli._success("Command completed successfully!")
|
|
1866
|
+
else:
|
|
1867
|
+
cli._error("Command execution failed")
|
|
1868
|
+
sys.exit(1)
|
|
1869
|
+
else:
|
|
1870
|
+
# Unknown command - show suggestions
|
|
1871
|
+
cli._warning(f"I didn't understand: '{user_input}'")
|
|
1872
|
+
cli._info("Try something like:")
|
|
1873
|
+
cli._info(' createsonline "create new project called myapp"')
|
|
1874
|
+
cli._info(' createsonline "start development server"')
|
|
1875
|
+
cli._info(' createsonline "show framework info"')
|
|
1876
|
+
cli._info(' createsonline help')
|
|
1877
|
+
sys.exit(1)
|
|
1878
|
+
|
|
1879
|
+
|
|
1880
|
+
def run_cli():
|
|
1881
|
+
"""Synchronous CLI runner"""
|
|
1882
|
+
try:
|
|
1883
|
+
if sys.version_info >= (3, 7):
|
|
1884
|
+
asyncio.run(main())
|
|
1885
|
+
else:
|
|
1886
|
+
# Fallback for older Python versions
|
|
1887
|
+
loop = asyncio.get_event_loop()
|
|
1888
|
+
loop.run_until_complete(main())
|
|
1889
|
+
except KeyboardInterrupt:
|
|
1890
|
+
print("\nâš ï¸ Operation cancelled by user")
|
|
1891
|
+
sys.exit(1)
|
|
1892
|
+
except Exception as e:
|
|
1893
|
+
print(f"⌠CLI Error: {e}")
|
|
1894
|
+
sys.exit(1)
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
# ========================================
|
|
1898
|
+
# LEGACY COMMAND SUPPORT (Optional)
|
|
1899
|
+
# ========================================
|
|
1900
|
+
|
|
1901
|
+
def serve(
|
|
1902
|
+
port: int = 8000,
|
|
1903
|
+
host: str = "127.0.0.1",
|
|
1904
|
+
reload: bool = True,
|
|
1905
|
+
workers: int = 1
|
|
1906
|
+
):
|
|
1907
|
+
"""Legacy serve command for backward compatibility"""
|
|
1908
|
+
print("🔄 Converting to natural language...")
|
|
1909
|
+
cmd = f"start development server on port {port}"
|
|
1910
|
+
sys.argv = ["createsonline", cmd]
|
|
1911
|
+
run_cli()
|
|
1912
|
+
|
|
1913
|
+
|
|
1914
|
+
def dev(port: int = 8000, host: str = "127.0.0.1"):
|
|
1915
|
+
"""Legacy dev command"""
|
|
1916
|
+
serve(port=port, host=host, reload=True)
|
|
1917
|
+
|
|
1918
|
+
|
|
1919
|
+
def prod(port: int = 8000, workers: int = 4):
|
|
1920
|
+
"""Legacy production command"""
|
|
1921
|
+
cmd = f"start production server with {workers} workers"
|
|
1922
|
+
sys.argv = ["createsonline", cmd]
|
|
1923
|
+
run_cli()
|
|
1924
|
+
|
|
1925
|
+
|
|
1926
|
+
def new(project_name: str, ai: bool = True, admin: bool = True, auth: bool = True):
|
|
1927
|
+
"""Legacy new project command"""
|
|
1928
|
+
features = []
|
|
1929
|
+
if ai:
|
|
1930
|
+
features.append("with ai features")
|
|
1931
|
+
if admin:
|
|
1932
|
+
features.append("with admin")
|
|
1933
|
+
if auth:
|
|
1934
|
+
features.append("with auth")
|
|
1935
|
+
|
|
1936
|
+
cmd = f"create new project called {project_name} {' '.join(features)}"
|
|
1937
|
+
sys.argv = ["createsonline", cmd]
|
|
1938
|
+
run_cli()
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
def info():
|
|
1942
|
+
"""Legacy info command"""
|
|
1943
|
+
sys.argv = ["createsonline", "show framework info"]
|
|
1944
|
+
run_cli()
|
|
1945
|
+
|
|
1946
|
+
|
|
1947
|
+
def version():
|
|
1948
|
+
"""Legacy version command"""
|
|
1949
|
+
sys.argv = ["createsonline", "version"]
|
|
1950
|
+
run_cli()
|
|
1951
|
+
|
|
1952
|
+
|
|
1953
|
+
def shell():
|
|
1954
|
+
"""Legacy shell command"""
|
|
1955
|
+
sys.argv = ["createsonline", "shell"]
|
|
1956
|
+
run_cli()
|
|
1957
|
+
|
|
1958
|
+
|
|
1959
|
+
def createsuperuser():
|
|
1960
|
+
"""Legacy createsuperuser command"""
|
|
1961
|
+
sys.argv = ["createsonline", "create superuser"]
|
|
1962
|
+
run_cli()
|
|
1963
|
+
|
|
1964
|
+
|
|
1965
|
+
# ========================================
|
|
1966
|
+
# TYPER APP FALLBACK (If Available)
|
|
1967
|
+
# ========================================
|
|
1968
|
+
|
|
1969
|
+
if TYPER_AVAILABLE:
|
|
1970
|
+
# Create Typer app for advanced users who prefer traditional CLI
|
|
1971
|
+
typer_app = typer.Typer(
|
|
1972
|
+
name="createsonline",
|
|
1973
|
+
help="CREATESONLINE Framework - Natural Language CLI",
|
|
1974
|
+
add_completion=False,
|
|
1975
|
+
rich_markup_mode="rich",
|
|
1976
|
+
no_args_is_help=True
|
|
1977
|
+
)
|
|
1978
|
+
|
|
1979
|
+
# Add legacy commands to Typer app
|
|
1980
|
+
typer_app.command("serve")(serve)
|
|
1981
|
+
typer_app.command("dev")(dev)
|
|
1982
|
+
typer_app.command("prod")(prod)
|
|
1983
|
+
typer_app.command("new")(new)
|
|
1984
|
+
typer_app.command("info")(info)
|
|
1985
|
+
typer_app.command("version")(version)
|
|
1986
|
+
typer_app.command("shell")(shell)
|
|
1987
|
+
typer_app.command("createsuperuser")(createsuperuser)
|
|
1988
|
+
|
|
1989
|
+
# Main command that handles natural language
|
|
1990
|
+
@typer_app.callback(invoke_without_command=True)
|
|
1991
|
+
def main_callback(
|
|
1992
|
+
ctx, # FIXED: Remove type annotation to avoid stub issues
|
|
1993
|
+
natural_command: str = typer.Argument(None, help="Natural language command")
|
|
1994
|
+
):
|
|
1995
|
+
"""
|
|
1996
|
+
C⎯◠CREATESONLINE Natural Language CLI
|
|
1997
|
+
|
|
1998
|
+
Express your intent naturally:
|
|
1999
|
+
createsonline "create new AI-powered project called blog"
|
|
2000
|
+
createsonline "start development server on port 8000"
|
|
2001
|
+
"""
|
|
2002
|
+
if ctx.invoked_subcommand is None:
|
|
2003
|
+
if natural_command:
|
|
2004
|
+
sys.argv = ["createsonline", natural_command]
|
|
2005
|
+
run_cli()
|
|
2006
|
+
else:
|
|
2007
|
+
# Show help
|
|
2008
|
+
sys.argv = ["createsonline", "help"]
|
|
2009
|
+
run_cli()
|
|
2010
|
+
|
|
2011
|
+
# Export the Typer app
|
|
2012
|
+
app = typer_app
|
|
2013
|
+
|
|
2014
|
+
else:
|
|
2015
|
+
# No Typer available - use our internal implementation
|
|
2016
|
+
app = None
|
|
2017
|
+
|
|
2018
|
+
|
|
2019
|
+
# ========================================
|
|
2020
|
+
# MODULE EXPORTS
|
|
2021
|
+
# ========================================
|
|
2022
|
+
|
|
2023
|
+
__all__ = [
|
|
2024
|
+
'main',
|
|
2025
|
+
'run_cli',
|
|
2026
|
+
'CreatesonlineNaturalLanguageCLI',
|
|
2027
|
+
'serve',
|
|
2028
|
+
'dev',
|
|
2029
|
+
'prod',
|
|
2030
|
+
'new',
|
|
2031
|
+
'info',
|
|
2032
|
+
'version',
|
|
2033
|
+
'shell',
|
|
2034
|
+
'createsuperuser'
|
|
2035
|
+
]
|
|
2036
|
+
|
|
2037
|
+
# Entry point for console scripts
|
|
2038
|
+
if __name__ == "__main__":
|
|
2039
|
+
run_cli()
|
|
2040
|
+
|
|
2041
|
+
|