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,416 @@
|
|
|
1
|
+
# createsonline/cli/commands/database.py
|
|
2
|
+
"""
|
|
3
|
+
CREATESONLINE Database Commands
|
|
4
|
+
|
|
5
|
+
Database management and AI query commands for the CLI.
|
|
6
|
+
Provides natural language database querying and audit capabilities.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Dict, Any, List, Optional
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
|
|
14
|
+
# Internal console implementation (fallback for rich)
|
|
15
|
+
try:
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.panel import Panel
|
|
18
|
+
from rich.table import Table
|
|
19
|
+
from rich.syntax import Syntax
|
|
20
|
+
from rich.prompt import Confirm
|
|
21
|
+
RICH_AVAILABLE = True
|
|
22
|
+
console = Console()
|
|
23
|
+
except ImportError:
|
|
24
|
+
RICH_AVAILABLE = False
|
|
25
|
+
# Internal console fallback
|
|
26
|
+
class SimpleConsole:
|
|
27
|
+
def print(self, text, **kwargs):
|
|
28
|
+
if isinstance(text, str):
|
|
29
|
+
import logging as _logging; _logging.getLogger("createsonline.cli.database").info(text)
|
|
30
|
+
else:
|
|
31
|
+
import logging as _logging; _logging.getLogger("createsonline.cli.database").info(str(text))
|
|
32
|
+
|
|
33
|
+
def input(self, prompt):
|
|
34
|
+
return input(prompt)
|
|
35
|
+
|
|
36
|
+
console = SimpleConsole()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def db_ai_query_command(
|
|
40
|
+
prompt: str,
|
|
41
|
+
approve: bool = False,
|
|
42
|
+
explain: bool = False,
|
|
43
|
+
save: str = None,
|
|
44
|
+
output_format: str = "table"
|
|
45
|
+
):
|
|
46
|
+
"""🤖 AI-powered natural language database queries
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
createsonline db ai-query "show last 10 users"
|
|
50
|
+
createsonline db ai-query "how many active users" --approve
|
|
51
|
+
createsonline db ai-query "list admin users" --explain
|
|
52
|
+
createsonline db ai-query "recent error logs" --save recent-errors
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
try:
|
|
56
|
+
# Import database assistant - use the main database.py file
|
|
57
|
+
import os
|
|
58
|
+
import importlib.util
|
|
59
|
+
|
|
60
|
+
# Get the path to the main database.py file
|
|
61
|
+
current_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
|
62
|
+
db_path = os.path.join(current_dir, 'database.py')
|
|
63
|
+
|
|
64
|
+
# Load the database module
|
|
65
|
+
spec = importlib.util.spec_from_file_location("database_main", db_path)
|
|
66
|
+
db_module = importlib.util.module_from_spec(spec)
|
|
67
|
+
spec.loader.exec_module(db_module)
|
|
68
|
+
|
|
69
|
+
# Load the assistant module
|
|
70
|
+
assistant_path = os.path.join(current_dir, 'database', 'assistant.py')
|
|
71
|
+
spec = importlib.util.spec_from_file_location("assistant", assistant_path)
|
|
72
|
+
assistant_module = importlib.util.module_from_spec(spec)
|
|
73
|
+
spec.loader.exec_module(assistant_module)
|
|
74
|
+
|
|
75
|
+
# Initialize database and assistant
|
|
76
|
+
db = db_module.get_database()
|
|
77
|
+
assistant = assistant_module.create_assistant(db)
|
|
78
|
+
|
|
79
|
+
if RICH_AVAILABLE:
|
|
80
|
+
console.print(Panel(
|
|
81
|
+
f"[bold blue]🤖 CREATESONLINE Database AI Assistant[/bold blue]\n"
|
|
82
|
+
f"[cyan]Natural Language → SQL Query[/cyan]\n\n"
|
|
83
|
+
f"[green]Prompt:[/green] {prompt}\n"
|
|
84
|
+
f"[green]Safety:[/green] SELECT-only mode\n"
|
|
85
|
+
f"[green]Audit:[/green] All queries logged",
|
|
86
|
+
title="ðŸ—„ï¸ Database AI Query",
|
|
87
|
+
border_style="blue"
|
|
88
|
+
))
|
|
89
|
+
else:
|
|
90
|
+
console.print("CREATESONLINE Database AI Assistant") if RICH_AVAILABLE else __import__("logging").getLogger("createsonline.cli.database").info("CREATESONLINE Database AI Assistant")
|
|
91
|
+
(console.print(f"Prompt: {prompt}") if RICH_AVAILABLE else __import__("logging").getLogger("createsonline.cli.database").info(f"Prompt: {prompt}"))
|
|
92
|
+
# Handle explain mode
|
|
93
|
+
if explain:
|
|
94
|
+
try:
|
|
95
|
+
parsed = assistant.parse_natural_language(prompt)
|
|
96
|
+
_display_explanation(parsed)
|
|
97
|
+
return
|
|
98
|
+
except Exception as e:
|
|
99
|
+
if RICH_AVAILABLE:
|
|
100
|
+
console.print(f"[red]⌠Failed to parse query: {e}[/red]")
|
|
101
|
+
else:
|
|
102
|
+
__import__("logging").getLogger("createsonline.cli.database").error(f"Failed to parse query: {e}")
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
# Parse and generate SQL
|
|
106
|
+
try:
|
|
107
|
+
parsed_query = assistant.parse_natural_language(prompt)
|
|
108
|
+
sql = assistant.generate_sql(parsed_query)
|
|
109
|
+
|
|
110
|
+
# Create result structure
|
|
111
|
+
result = {
|
|
112
|
+
'success': True,
|
|
113
|
+
'sql': sql,
|
|
114
|
+
'parsed_query': parsed_query,
|
|
115
|
+
'prompt': prompt
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
except Exception as e:
|
|
119
|
+
result = {
|
|
120
|
+
'success': False,
|
|
121
|
+
'error': str(e),
|
|
122
|
+
'prompt': prompt
|
|
123
|
+
}
|
|
124
|
+
_display_error(result)
|
|
125
|
+
return
|
|
126
|
+
|
|
127
|
+
# Ask for confirmation if not auto-approved
|
|
128
|
+
if not approve and not _confirm_execution(result):
|
|
129
|
+
console.print("⌠Query cancelled by user")
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
# Execute the query
|
|
133
|
+
try:
|
|
134
|
+
query_results = assistant.execute_safe(result['sql'], result['parsed_query'])
|
|
135
|
+
result['data'] = query_results.get('results', [])
|
|
136
|
+
result['rows_affected'] = len(result['data'])
|
|
137
|
+
except Exception as e:
|
|
138
|
+
result['success'] = False
|
|
139
|
+
result['error'] = str(e)
|
|
140
|
+
_display_error(result)
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
# Display results
|
|
144
|
+
_display_results(result, output_format)
|
|
145
|
+
|
|
146
|
+
# Save as reusable command if requested
|
|
147
|
+
if save:
|
|
148
|
+
_save_command(save, prompt, result)
|
|
149
|
+
|
|
150
|
+
except Exception as e:
|
|
151
|
+
if RICH_AVAILABLE:
|
|
152
|
+
console.print(f"[red]⌠Database AI Query Error: {e}[/red]")
|
|
153
|
+
else:
|
|
154
|
+
__import__("logging").getLogger("createsonline.cli.database").error(f"Database AI Query Error: {e}")
|
|
155
|
+
def db_rollback_command(audit_id: int = None, last: bool = False, dry_run: bool = False):
|
|
156
|
+
"""🔄 Rollback database operations using audit logs
|
|
157
|
+
|
|
158
|
+
Examples:
|
|
159
|
+
createsonline db rollback --last
|
|
160
|
+
createsonline db rollback --id 42
|
|
161
|
+
createsonline db rollback --last --dry-run
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
from ...database.assistant import create_assistant
|
|
166
|
+
from ...database import get_database
|
|
167
|
+
|
|
168
|
+
db = get_database()
|
|
169
|
+
assistant = create_assistant(db)
|
|
170
|
+
|
|
171
|
+
if RICH_AVAILABLE:
|
|
172
|
+
console.print(Panel(
|
|
173
|
+
"[bold yellow]🔄 Database Rollback Assistant[/bold yellow]\n"
|
|
174
|
+
"[orange]Undo database operations safely[/orange]",
|
|
175
|
+
title="ðŸ—„ï¸ Database Rollback",
|
|
176
|
+
border_style="yellow"
|
|
177
|
+
))
|
|
178
|
+
else:
|
|
179
|
+
__import__("logging").getLogger("createsonline.cli.database").info("Database Rollback Assistant")
|
|
180
|
+
# Get audit entries to rollback
|
|
181
|
+
if last:
|
|
182
|
+
recent_queries = assistant.get_recent_queries(1)
|
|
183
|
+
if not recent_queries:
|
|
184
|
+
console.print("⌠No recent queries found")
|
|
185
|
+
return
|
|
186
|
+
audit_entry = recent_queries[0]
|
|
187
|
+
elif audit_id:
|
|
188
|
+
# TODO: Implement get_audit_by_id
|
|
189
|
+
console.print("⌠Rollback by ID not yet implemented")
|
|
190
|
+
return
|
|
191
|
+
else:
|
|
192
|
+
console.print("⌠Must specify either --last or --id")
|
|
193
|
+
return
|
|
194
|
+
|
|
195
|
+
# Display what would be rolled back
|
|
196
|
+
_display_rollback_preview(audit_entry)
|
|
197
|
+
|
|
198
|
+
if dry_run:
|
|
199
|
+
console.print("✅ Dry-run complete - no changes made")
|
|
200
|
+
return
|
|
201
|
+
|
|
202
|
+
# Confirm rollback
|
|
203
|
+
if not Confirm.ask("Proceed with rollback?") if RICH_AVAILABLE else input("Proceed with rollback? (y/N): ").lower().startswith('y'):
|
|
204
|
+
console.print("⌠Rollback cancelled")
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
# For now, only log the rollback intent (actual rollback logic would be complex)
|
|
208
|
+
console.print("âš ï¸ Rollback functionality is logged but not yet implemented")
|
|
209
|
+
console.print("This is a safety feature - manual review recommended")
|
|
210
|
+
|
|
211
|
+
except Exception as e:
|
|
212
|
+
console.print(f"⌠Rollback Error: {e}")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def db_audit_log_command(limit: int = 20, filter_type: str = None):
|
|
216
|
+
"""📋 View database operation audit logs
|
|
217
|
+
|
|
218
|
+
Examples:
|
|
219
|
+
createsonline db audit-log
|
|
220
|
+
createsonline db audit-log --limit 50
|
|
221
|
+
createsonline db audit-log --filter-type error
|
|
222
|
+
"""
|
|
223
|
+
|
|
224
|
+
try:
|
|
225
|
+
from ...database.assistant import create_assistant
|
|
226
|
+
from ...database import get_database
|
|
227
|
+
|
|
228
|
+
db = get_database()
|
|
229
|
+
assistant = create_assistant(db)
|
|
230
|
+
|
|
231
|
+
if RICH_AVAILABLE:
|
|
232
|
+
console.print(Panel(
|
|
233
|
+
"[bold green]📋 Database Audit Log[/bold green]\n"
|
|
234
|
+
"[cyan]Recent database operations[/cyan]",
|
|
235
|
+
title="ðŸ—„ï¸ Audit Log",
|
|
236
|
+
border_style="green"
|
|
237
|
+
))
|
|
238
|
+
else:
|
|
239
|
+
__import__("logging").getLogger("createsonline.cli.database").info("Database Audit Log")
|
|
240
|
+
# Get recent queries
|
|
241
|
+
recent_queries = assistant.get_recent_queries(limit)
|
|
242
|
+
|
|
243
|
+
if not recent_queries:
|
|
244
|
+
console.print("â„¹ï¸ No audit log entries found")
|
|
245
|
+
return
|
|
246
|
+
|
|
247
|
+
# Filter if requested
|
|
248
|
+
if filter_type:
|
|
249
|
+
recent_queries = [q for q in recent_queries if q.get('status') == filter_type]
|
|
250
|
+
|
|
251
|
+
# Display audit log
|
|
252
|
+
_display_audit_log(recent_queries)
|
|
253
|
+
|
|
254
|
+
except Exception as e:
|
|
255
|
+
console.print(f"⌠Audit Log Error: {e}")
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _display_explanation(parsed_query: Dict[str, Any]):
|
|
259
|
+
"""Display query explanation"""
|
|
260
|
+
if RICH_AVAILABLE:
|
|
261
|
+
# Create explanation panel
|
|
262
|
+
explanation_content = f"""
|
|
263
|
+
[yellow]Original Prompt:[/yellow] {parsed_query['original_prompt']}
|
|
264
|
+
|
|
265
|
+
[yellow]Query Type:[/yellow] {parsed_query['query_type'].value.upper()}
|
|
266
|
+
[yellow]Target Table:[/yellow] {parsed_query['table']}
|
|
267
|
+
[yellow]Safety Level:[/yellow] {parsed_query['safety_level'].value}
|
|
268
|
+
[yellow]Columns:[/yellow] {', '.join(parsed_query['columns'])}
|
|
269
|
+
|
|
270
|
+
[yellow]Conditions:[/yellow] {len(parsed_query['conditions'])} conditions
|
|
271
|
+
[yellow]Limit:[/yellow] {parsed_query.get('limit', 'None')}
|
|
272
|
+
[yellow]Order By:[/yellow] {parsed_query.get('order_by', 'None')}
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
console.print(Panel(
|
|
276
|
+
explanation_content,
|
|
277
|
+
title="🔠Query Explanation",
|
|
278
|
+
border_style="yellow"
|
|
279
|
+
))
|
|
280
|
+
else:
|
|
281
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Prompt: {parsed_query['original_prompt']}")
|
|
282
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Query Type: {parsed_query['query_type'].value}")
|
|
283
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Target Table: {parsed_query['table']}")
|
|
284
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Safety Level: {parsed_query['safety_level'].value}")
|
|
285
|
+
console.print(Panel(
|
|
286
|
+
explanation_content,
|
|
287
|
+
title="🔠Query Explanation",
|
|
288
|
+
border_style="yellow"
|
|
289
|
+
))
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _display_error(result: Dict[str, Any]):
|
|
293
|
+
"""Display error information"""
|
|
294
|
+
if RICH_AVAILABLE:
|
|
295
|
+
console.print(Panel(
|
|
296
|
+
f"[red]Error: {result['error']}[/red]\n"
|
|
297
|
+
f"[yellow]Prompt: {result['prompt']}[/yellow]",
|
|
298
|
+
title="⌠Query Failed",
|
|
299
|
+
border_style="red"
|
|
300
|
+
))
|
|
301
|
+
else:
|
|
302
|
+
__import__("logging").getLogger("createsonline.cli.database").error(f"Error: {result['error']}")
|
|
303
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Prompt: {result['prompt']}" )
|
|
304
|
+
def _confirm_execution(result: Dict[str, Any]) -> bool:
|
|
305
|
+
"""Ask user to confirm query execution"""
|
|
306
|
+
if not RICH_AVAILABLE:
|
|
307
|
+
response = input(f"Execute SQL: {result.get('sql', 'Unknown')}? (y/N): ")
|
|
308
|
+
return response.lower().startswith('y')
|
|
309
|
+
|
|
310
|
+
# Display query preview
|
|
311
|
+
sql = result.get('sql', 'Unknown')
|
|
312
|
+
|
|
313
|
+
console.print(Panel(
|
|
314
|
+
f"[yellow]Generated SQL:[/yellow]\n{sql}\n\n"
|
|
315
|
+
f"[cyan]This query will be executed against your database.[/cyan]",
|
|
316
|
+
title="🔠Confirm Execution",
|
|
317
|
+
border_style="yellow"
|
|
318
|
+
))
|
|
319
|
+
|
|
320
|
+
return Confirm.ask("Execute this query?")
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _display_results(result: Dict[str, Any], output_format: str):
|
|
324
|
+
"""Display query results in specified format"""
|
|
325
|
+
data = result['data']
|
|
326
|
+
|
|
327
|
+
if output_format == "json":
|
|
328
|
+
__import__("logging").getLogger("createsonline.cli.database").info(json.dumps(data, indent=2, default=str))
|
|
329
|
+
return
|
|
330
|
+
|
|
331
|
+
if not data:
|
|
332
|
+
console.print("â„¹ï¸ No results found")
|
|
333
|
+
return
|
|
334
|
+
|
|
335
|
+
if RICH_AVAILABLE and output_format == "table":
|
|
336
|
+
# Create rich table
|
|
337
|
+
table = Table(title=f"Query Results ({len(data)} rows)")
|
|
338
|
+
|
|
339
|
+
# Add columns based on first row
|
|
340
|
+
if data and isinstance(data[0], dict):
|
|
341
|
+
for column in data[0].keys():
|
|
342
|
+
table.add_column(str(column), style="cyan")
|
|
343
|
+
|
|
344
|
+
# Add rows
|
|
345
|
+
for row in data:
|
|
346
|
+
table.add_row(*[str(value) for value in row.values()])
|
|
347
|
+
|
|
348
|
+
console.print(table)
|
|
349
|
+
|
|
350
|
+
# Show execution info
|
|
351
|
+
console.print(f"\n✅ Query executed successfully")
|
|
352
|
+
console.print(f"📊 Rows returned: {result['rows_returned']}")
|
|
353
|
+
console.print(f"â±ï¸ Execution time: {result['execution_time']}")
|
|
354
|
+
else:
|
|
355
|
+
# Simple text output
|
|
356
|
+
console.print(f"Results ({len(data)} rows):") if RICH_AVAILABLE else __import__("logging").getLogger("createsonline.cli.database").info(f"Results ({len(data)} rows):")
|
|
357
|
+
for i, row in enumerate(data):
|
|
358
|
+
console.print(f"Row {i+1}: {row}") if RICH_AVAILABLE else __import__("logging").getLogger("createsonline.cli.database").info(f"Row {i+1}: {row}")
|
|
359
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Query executed successfully - {result['rows_returned']} rows")
|
|
360
|
+
def _display_rollback_preview(audit_entry: Dict[str, Any]):
|
|
361
|
+
"""Display rollback preview"""
|
|
362
|
+
if RICH_AVAILABLE:
|
|
363
|
+
preview_content = f"""
|
|
364
|
+
[yellow]Operation to Rollback:[/yellow]
|
|
365
|
+
[white]Timestamp:[/white] {audit_entry.get('timestamp', 'Unknown')}
|
|
366
|
+
[white]Original Prompt:[/white] {audit_entry.get('original_prompt', 'N/A')}
|
|
367
|
+
[white]SQL Query:[/white] {audit_entry.get('sql_query', 'Unknown')}
|
|
368
|
+
[white]Status:[/white] {audit_entry.get('status', 'Unknown')}
|
|
369
|
+
[white]Rows Affected:[/white] {audit_entry.get('rows_affected', 0)}
|
|
370
|
+
|
|
371
|
+
[red]âš ï¸ Rollback operations are complex and may not be reversible.[/red]
|
|
372
|
+
[red]Manual verification is strongly recommended.[/red]
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
console.print(Panel(
|
|
376
|
+
preview_content,
|
|
377
|
+
title="🔄 Rollback Preview",
|
|
378
|
+
border_style="yellow"
|
|
379
|
+
))
|
|
380
|
+
else:
|
|
381
|
+
console.print("Operation to Rollback:") if RICH_AVAILABLE else __import__("logging").getLogger("createsonline.cli.database").info("Operation to Rollback:")
|
|
382
|
+
pass
|
|
383
|
+
pass
|
|
384
|
+
pass
|
|
385
|
+
def _display_audit_log(entries: List[Dict[str, Any]]):
|
|
386
|
+
"""Display audit log entries"""
|
|
387
|
+
if RICH_AVAILABLE:
|
|
388
|
+
table = Table(title=f"Database Audit Log ({len(entries)} entries)")
|
|
389
|
+
table.add_column("Timestamp", style="cyan")
|
|
390
|
+
table.add_column("Prompt", style="yellow")
|
|
391
|
+
table.add_column("Status", style="green")
|
|
392
|
+
table.add_column("Rows", style="blue")
|
|
393
|
+
table.add_column("Error", style="red")
|
|
394
|
+
|
|
395
|
+
for entry in entries:
|
|
396
|
+
table.add_row(
|
|
397
|
+
str(entry.get('timestamp', 'Unknown'))[:19], # Truncate timestamp
|
|
398
|
+
str(entry.get('original_prompt', 'N/A'))[:50] + ('...' if len(str(entry.get('original_prompt', ''))) > 50 else ''),
|
|
399
|
+
str(entry.get('status', 'Unknown')),
|
|
400
|
+
str(entry.get('rows_affected', 0)),
|
|
401
|
+
str(entry.get('error_message', ''))[:30] + ('...' if len(str(entry.get('error_message', ''))) > 30 else '')
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
console.print(table)
|
|
405
|
+
else:
|
|
406
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"Audit Log ({len(entries)} entries):")
|
|
407
|
+
for i, entry in enumerate(entries):
|
|
408
|
+
__import__("logging").getLogger("createsonline.cli.database").info(f"{i+1}. {entry.get('timestamp', 'Unknown')} - {entry.get('original_prompt', 'N/A')} [{entry.get('status', 'Unknown')}]")
|
|
409
|
+
def _save_command(name: str, prompt: str, result: Dict[str, Any]):
|
|
410
|
+
"""Save successful query as reusable CLI command"""
|
|
411
|
+
# TODO: Implement command saving to config file
|
|
412
|
+
console.print(f"💾 Command saving not yet implemented")
|
|
413
|
+
console.print(f"Would save: '{name}' -> '{prompt}'")
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# createsonline/cli/commands/info.py
|
|
2
|
+
"""
|
|
3
|
+
CREATESONLINE Info Commands
|
|
4
|
+
|
|
5
|
+
Provides info and version commands.
|
|
6
|
+
"""
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from rich.table import Table
|
|
10
|
+
from rich.columns import Columns
|
|
11
|
+
import sys
|
|
12
|
+
import platform
|
|
13
|
+
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
def info_command():
|
|
17
|
+
"""📋 Show comprehensive framework information"""
|
|
18
|
+
|
|
19
|
+
# Get framework info
|
|
20
|
+
try:
|
|
21
|
+
import createsonline
|
|
22
|
+
framework_info = createsonline.get_framework_info()
|
|
23
|
+
ai_available = True
|
|
24
|
+
try:
|
|
25
|
+
import createsonline.ai
|
|
26
|
+
ai_info = createsonline.ai.get_ai_info()
|
|
27
|
+
except:
|
|
28
|
+
ai_available = False
|
|
29
|
+
ai_info = {}
|
|
30
|
+
except ImportError:
|
|
31
|
+
framework_info = {
|
|
32
|
+
"name": "CREATESONLINE",
|
|
33
|
+
"version": "0.1.0",
|
|
34
|
+
"tagline": "Build Intelligence Into Everything"
|
|
35
|
+
}
|
|
36
|
+
ai_available = False
|
|
37
|
+
ai_info = {}
|
|
38
|
+
|
|
39
|
+
# Framework banner
|
|
40
|
+
banner = Panel(
|
|
41
|
+
f"[bold blue]{framework_info.get('name', 'CREATESONLINE')}[/bold blue]\n"
|
|
42
|
+
f"[cyan]{framework_info.get('tagline', 'Build Intelligence Into Everything')}[/cyan]\n\n"
|
|
43
|
+
f"[green]Version:[/green] {framework_info.get('version', '0.1.0')}\n"
|
|
44
|
+
f"[green]Python:[/green] {sys.version.split()[0]}\n"
|
|
45
|
+
f"[green]Platform:[/green] {platform.system()} {platform.release()}",
|
|
46
|
+
title="C⎯● Framework Information",
|
|
47
|
+
border_style="blue"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Features table
|
|
51
|
+
features_table = Table(title="✨ Framework Features", show_header=False)
|
|
52
|
+
features_table.add_column("Feature", style="cyan")
|
|
53
|
+
features_table.add_column("Status", style="green")
|
|
54
|
+
|
|
55
|
+
features = framework_info.get('features', [
|
|
56
|
+
"Pure AI-Native Architecture",
|
|
57
|
+
"Built-in Admin Interface",
|
|
58
|
+
"User Management System",
|
|
59
|
+
"AI-Enhanced ORM",
|
|
60
|
+
"Natural Language Queries",
|
|
61
|
+
"Vector Similarity Search",
|
|
62
|
+
"LLM Integration",
|
|
63
|
+
"Beautiful CLI Tools"
|
|
64
|
+
])
|
|
65
|
+
|
|
66
|
+
for feature in features:
|
|
67
|
+
features_table.add_row(f"• {feature}", "✅ Available")
|
|
68
|
+
|
|
69
|
+
# AI info table
|
|
70
|
+
ai_table = Table(title="C⎯● AI Capabilities", show_header=False)
|
|
71
|
+
ai_table.add_column("Capability", style="cyan")
|
|
72
|
+
ai_table.add_column("Status", style="green" if ai_available else "yellow")
|
|
73
|
+
|
|
74
|
+
if ai_available and ai_info:
|
|
75
|
+
field_types = ai_info.get('field_types', [])
|
|
76
|
+
services = ai_info.get('services', [])
|
|
77
|
+
capabilities = ai_info.get('capabilities', [])
|
|
78
|
+
|
|
79
|
+
ai_table.add_row("AI Module", "✅ Available" if ai_available else "⚠️ Limited")
|
|
80
|
+
ai_table.add_row(f"Field Types", f"✅ {len(field_types)} types")
|
|
81
|
+
ai_table.add_row(f"AI Services", f"✅ {len(services)} services")
|
|
82
|
+
ai_table.add_row(f"Capabilities", f"✅ {len(capabilities)} features")
|
|
83
|
+
else:
|
|
84
|
+
ai_table.add_row("AI Module", "⚠️ Limited Mode")
|
|
85
|
+
ai_table.add_row("Field Types", "⚠️ Basic support")
|
|
86
|
+
ai_table.add_row("AI Services", "⚠️ Mock services")
|
|
87
|
+
ai_table.add_row("Capabilities", "⚠️ Reduced functionality")
|
|
88
|
+
|
|
89
|
+
# Dependencies table
|
|
90
|
+
deps_table = Table(title="📦 Core Dependencies", show_header=False)
|
|
91
|
+
deps_table.add_column("Package", style="cyan")
|
|
92
|
+
deps_table.add_column("Status", style="green")
|
|
93
|
+
|
|
94
|
+
core_deps = [
|
|
95
|
+
("uvicorn", "ASGI Server"),
|
|
96
|
+
("sqlalchemy", "Database ORM"),
|
|
97
|
+
("typer", "CLI Framework"),
|
|
98
|
+
("rich", "Terminal UI"),
|
|
99
|
+
("pydantic", "Data Validation")
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
for pkg, desc in core_deps:
|
|
103
|
+
try:
|
|
104
|
+
__import__(pkg)
|
|
105
|
+
status = "✅ Installed"
|
|
106
|
+
except ImportError:
|
|
107
|
+
status = "❌ Missing"
|
|
108
|
+
deps_table.add_row(f"{pkg} ({desc})", status)
|
|
109
|
+
|
|
110
|
+
# Display everything
|
|
111
|
+
console.print(banner)
|
|
112
|
+
console.print("\n")
|
|
113
|
+
|
|
114
|
+
# Show tables in columns
|
|
115
|
+
console.print(Columns([features_table, ai_table]))
|
|
116
|
+
console.print("\n")
|
|
117
|
+
console.print(deps_table)
|
|
118
|
+
|
|
119
|
+
# Commands info
|
|
120
|
+
commands_info = Panel(
|
|
121
|
+
"[bold green]Available Commands:[/bold green]\n\n"
|
|
122
|
+
"[cyan]createsonline serve[/cyan] - Start development server\n"
|
|
123
|
+
"[cyan]createsonline dev[/cyan] - Development mode with auto-reload\n"
|
|
124
|
+
"[cyan]createsonline prod[/cyan] - Production server\n"
|
|
125
|
+
"[cyan]createsonline new[/cyan] - Create new project\n"
|
|
126
|
+
"[cyan]createsonline info[/cyan] - Show this information\n"
|
|
127
|
+
"[cyan]createsonline version[/cyan] - Show version\n"
|
|
128
|
+
"[cyan]createsonline shell[/cyan] - Interactive shell\n"
|
|
129
|
+
"[cyan]createsonline createsuperuser[/cyan] - Create admin user",
|
|
130
|
+
title="🚀 CLI Commands",
|
|
131
|
+
border_style="green"
|
|
132
|
+
)
|
|
133
|
+
console.print(commands_info)
|
|
134
|
+
|
|
135
|
+
def version_command():
|
|
136
|
+
"""📦 Show version information"""
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
import createsonline
|
|
140
|
+
version = createsonline.__version__
|
|
141
|
+
name = createsonline.__framework_name__
|
|
142
|
+
tagline = createsonline.__tagline__
|
|
143
|
+
except ImportError:
|
|
144
|
+
version = "0.1.0"
|
|
145
|
+
name = "CREATESONLINE"
|
|
146
|
+
tagline = "Build Intelligence Into Everything"
|
|
147
|
+
|
|
148
|
+
# Version banner
|
|
149
|
+
version_panel = Panel(
|
|
150
|
+
f"[bold blue]{name}[/bold blue] [bold white]{version}[/bold white]\n\n"
|
|
151
|
+
f"[cyan]{tagline}[/cyan]\n\n"
|
|
152
|
+
f"[green]Python:[/green] {sys.version.split()[0]}\n"
|
|
153
|
+
f"[green]Platform:[/green] {platform.system()}\n"
|
|
154
|
+
f"[green]Architecture:[/green] {platform.machine()}",
|
|
155
|
+
title="📦 Version Information",
|
|
156
|
+
border_style="blue"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
console.print(version_panel)
|
|
160
|
+
|
|
161
|
+
# Show Python and system info
|
|
162
|
+
sys_table = Table(title="🖥️ System Information", show_header=False)
|
|
163
|
+
sys_table.add_column("Property", style="cyan")
|
|
164
|
+
sys_table.add_column("Value", style="white")
|
|
165
|
+
|
|
166
|
+
sys_table.add_row("Python Version", sys.version.split()[0])
|
|
167
|
+
sys_table.add_row("Python Path", sys.executable)
|
|
168
|
+
sys_table.add_row("Platform", f"{platform.system()} {platform.release()}")
|
|
169
|
+
sys_table.add_row("Machine", platform.machine())
|
|
170
|
+
sys_table.add_row("Processor", platform.processor() or "Unknown")
|
|
171
|
+
|
|
172
|
+
console.print("\n")
|
|
173
|
+
console.print(sys_table)
|