nextpy-framework 3.7.3__tar.gz → 3.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/__init__.py +1 -1
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/cli.py +101 -361
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_renderer.py +19 -11
- nextpy_framework-3.8.0/.nextpy_framework/nextpy/main.py +72 -0
- nextpy_framework-3.8.0/.nextpy_framework/nextpy/psx/compiler/actions.py +878 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/compiler/handler_compiler.py +52 -11
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/components/component.py +18 -6
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/parser.py +117 -30
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/runtime.py +15 -4
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/decorators.py +460 -136
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/engine.py +60 -1
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/integration.py +18 -4
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/actions_runtime.py +157 -11
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/runtime/js_actions_runtime.py +232 -52
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0/.nextpy_framework/nextpy_framework.egg-info}/PKG-INFO +1 -1
- {nextpy_framework-3.7.3/.nextpy_framework/nextpy_framework.egg-info → nextpy_framework-3.8.0}/PKG-INFO +1 -1
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/pyproject.toml +1 -1
- nextpy_framework-3.7.3/.nextpy_framework/nextpy/main.py +0 -81
- nextpy_framework-3.7.3/.nextpy_framework/nextpy/psx/compiler/actions.py +0 -431
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/ast_parser.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/auth.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/builder.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/AutoDebug_v3.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIcon.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/debug/DebugIconFixed.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/feedback.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/form.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/head.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/hooks_provider.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/image.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/layout.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/link.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/loader.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/navigation.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/toast.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/ui.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components/visual.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/components.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/conf.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/config.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/builder.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/component_router.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/data_fetching.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_pages_simple.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/demo_router.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/renderer.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/router.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/core/sync.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/db.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/core.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/performance.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/ui.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/debug/websocket.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_server.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/dev_tools.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/errors.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/hooks_provider_new.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_preprocessor.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/jsx_transformer.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/performance.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/base.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/builtin.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins/config.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/plugins.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/ast_nodes.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/core/evaluator.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/language_server_lsp.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/psx_formatter.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/server_client_components.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/devtools/setup.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/hydration/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/renderer/renderer.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_full_integration.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/tests/test_html_attribute_support.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/utils/helpers.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/psx/vdom/vnode.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/py.typed +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/runtime/events.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/security.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/app.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/debug.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/server/middleware.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/source/conf.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/HANDLER_REGISTRATION_SYSTEM.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/setup_complete.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_autodebug_enhanced.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_cli_scaffolding.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_colors.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_component_rendering.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_conversion.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_critical_fixes.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_mode.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_demo_server.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_enhanced_handlers.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_extraction.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_final.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_fixes.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_handler_system.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_hydration_engine.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_integration.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_interactive_bug.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_edgecases.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_jsx_preprocessor.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_migration.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_modular_debug.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_routing.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_features.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_server_working.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_full.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_integration.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_tailwind_up_to_date.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/tests/test_websocket_complete.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/true_jsx.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/__init__.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/cache.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/email.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/file_upload.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/logging.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/search.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/seo.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/utils/validators.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy/websocket.py +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/SOURCES.txt +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/dependency_links.txt +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/entry_points.txt +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/requires.txt +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/.nextpy_framework/nextpy_framework.egg-info/top_level.txt +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/LICENSE +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/README.md +0 -0
- {nextpy_framework-3.7.3 → nextpy_framework-3.8.0}/setup.cfg +0 -0
|
@@ -243,7 +243,7 @@ def cli():
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
@cli.command()
|
|
246
|
-
@click.option("--port", "-p", default=
|
|
246
|
+
@click.option("--port", "-p", default=8000, help="Port to run the server on")
|
|
247
247
|
@click.option("--host", "-h", default="0.0.0.0", help="Host to bind to")
|
|
248
248
|
@click.option("--reload/--no-reload", default=True, help="Enable hot reload")
|
|
249
249
|
@click.option("--debug/--no-debug", default=True, help="Enable debug mode")
|
|
@@ -322,6 +322,7 @@ def dev(port: int, host: str, reload: bool, debug: bool):
|
|
|
322
322
|
# Enhanced reload patterns for JSX files
|
|
323
323
|
reload_includes = [
|
|
324
324
|
"*.py",
|
|
325
|
+
"*.psx",
|
|
325
326
|
"*.py.jsx",
|
|
326
327
|
"*.jsx",
|
|
327
328
|
"*.html",
|
|
@@ -993,7 +994,10 @@ def _generate_page(name: str):
|
|
|
993
994
|
page_path.parent.mkdir(parents=True, exist_ok=True)
|
|
994
995
|
|
|
995
996
|
content = f'''"""Generated {name} page"""
|
|
997
|
+
|
|
998
|
+
from nextpy.psx import interactive_component as component
|
|
996
999
|
|
|
1000
|
+
@component
|
|
997
1001
|
def {name.title()}(props = None):
|
|
998
1002
|
"""{name.title()} page component"""
|
|
999
1003
|
props = props or {{}}
|
|
@@ -1328,213 +1332,132 @@ module.exports = {
|
|
|
1328
1332
|
_create_traditional_homepage(project_dir)
|
|
1329
1333
|
|
|
1330
1334
|
(project_dir / "pages" / "index.py").write_text('''"""Interactive Homepage """
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1335
|
+
from nextpy.psx import interactive_component as component
|
|
1336
|
+
|
|
1334
1337
|
|
|
1335
1338
|
@component
|
|
1336
1339
|
def Home(props=None):
|
|
1337
1340
|
props = props or {}
|
|
1338
1341
|
title = props.get("title", "Welcome to NextPy!")
|
|
1339
1342
|
message = props.get("message", "Build amazing web apps with Python and True JSX")
|
|
1340
|
-
|
|
1343
|
+
|
|
1341
1344
|
return (
|
|
1342
|
-
<div class="min-h-screen
|
|
1343
|
-
<div class="
|
|
1344
|
-
<
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
Docs
|
|
1358
|
-
</a>
|
|
1359
|
-
</div>
|
|
1360
|
-
</div>
|
|
1345
|
+
<div class="flex flex-col items-center justify-between min-h-screen p-24 font-sans text-white bg-black">
|
|
1346
|
+
<div class="flex items-center justify-between w-full max-w-5xl text-sm">
|
|
1347
|
+
<p>
|
|
1348
|
+
Get started by editing index.py in the
|
|
1349
|
+
<code class="font-mono font-bold">/pages</code>
|
|
1350
|
+
directory.
|
|
1351
|
+
</p>
|
|
1352
|
+
<div>
|
|
1353
|
+
<a
|
|
1354
|
+
href="https://rahimstudios.dev"
|
|
1355
|
+
class="flex items-center gap-2 hover:underline"
|
|
1356
|
+
>
|
|
1357
|
+
By
|
|
1358
|
+
<span class="font-bold">RahimStudios</span>
|
|
1359
|
+
</a>
|
|
1361
1360
|
</div>
|
|
1362
|
-
</div>
|
|
1363
1361
|
</div>
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
</div>
|
|
1368
|
-
)
|
|
1369
1362
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
click.echo(" Created: pages/index.py ")
|
|
1363
|
+
<div class="flex flex-col items-center gap-8">
|
|
1364
|
+
<div class="flex items-center gap-4">
|
|
1365
|
+
<h1 class="text-6xl font-bold text-transparent bg-gradient-to-r from-blue-400 to-purple-600 bg-clip-text">
|
|
1366
|
+
NextPy
|
|
1367
|
+
</h1>
|
|
1368
|
+
<span class="inline-flex items-center justify-center w-12 h-12 text-lg font-bold bg-gray-800 rounded-full">
|
|
1369
|
+
3.7.3
|
|
1370
|
+
</span>
|
|
1371
|
+
</div>
|
|
1372
|
+
</div>
|
|
1381
1373
|
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1374
|
+
<div class="grid w-full max-w-5xl grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
1375
|
+
<a
|
|
1376
|
+
href="https://nextpy-framework.onrender.com/"
|
|
1377
|
+
class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
|
|
1378
|
+
>
|
|
1379
|
+
<h2 class="mb-3 text-2xl font-semibold">
|
|
1380
|
+
Docs
|
|
1381
|
+
<span class="inline-block transition-transform group-hover:translate-x-1">
|
|
1382
|
+
->
|
|
1383
|
+
</span>
|
|
1384
|
+
</h2>
|
|
1385
|
+
<p class="text-sm text-gray-400">
|
|
1386
|
+
Find in-depth information about NextPy features and API.
|
|
1387
|
+
</p>
|
|
1388
|
+
</a>
|
|
1385
1389
|
|
|
1386
|
-
|
|
1390
|
+
<a
|
|
1391
|
+
href="https://nextpy-framework.onrender.com/learn"
|
|
1392
|
+
class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
|
|
1393
|
+
>
|
|
1394
|
+
<h2 class="mb-3 text-2xl font-semibold">
|
|
1395
|
+
Learn
|
|
1396
|
+
<span class="inline-block transition-transform group-hover:translate-x-1">
|
|
1397
|
+
->
|
|
1398
|
+
</span>
|
|
1399
|
+
</h2>
|
|
1400
|
+
<p class="text-sm text-gray-400">
|
|
1401
|
+
Learn about NextPy in an interactive course with quizzes!
|
|
1402
|
+
</p>
|
|
1403
|
+
</a>
|
|
1387
1404
|
|
|
1405
|
+
<a
|
|
1406
|
+
href="https://nextpy-framework.onrender.com/templates"
|
|
1407
|
+
class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
|
|
1408
|
+
>
|
|
1409
|
+
<h2 class="mb-3 text-2xl font-semibold">
|
|
1410
|
+
Templates
|
|
1411
|
+
<span class="inline-block transition-transform group-hover:translate-x-1">
|
|
1412
|
+
->
|
|
1413
|
+
</span>
|
|
1414
|
+
</h2>
|
|
1415
|
+
<p class="text-sm text-gray-400">
|
|
1416
|
+
Explore starter templates for NextPy.
|
|
1417
|
+
</p>
|
|
1418
|
+
</a>
|
|
1388
1419
|
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
{title}
|
|
1404
|
-
</h1>
|
|
1405
|
-
<p class="max-w-2xl mx-auto mt-6 text-xl text-blue-100">
|
|
1406
|
-
{description}
|
|
1407
|
-
</p>
|
|
1408
|
-
<div class="flex justify-center mt-10 space-x-4">
|
|
1409
|
-
<a href="/features" class="inline-flex items-center justify-center px-8 py-3 text-base font-medium text-blue-600 bg-white border border-transparent rounded-md hover:bg-blue-50 md:py-4 md:text-lg md:px-10">
|
|
1410
|
-
Explore Features
|
|
1411
|
-
</a>
|
|
1412
|
-
<a href="/getting-started" class="inline-flex items-center justify-center px-8 py-3 text-base font-medium text-white bg-blue-500 border border-transparent rounded-md hover:bg-blue-600 md:py-4 md:text-lg md:px-10">
|
|
1413
|
-
Get Started
|
|
1414
|
-
</a>
|
|
1415
|
-
</div>
|
|
1416
|
-
</div>
|
|
1417
|
-
</div>
|
|
1420
|
+
<a
|
|
1421
|
+
href="https://nextpy-framework.onrender.com/deploy"
|
|
1422
|
+
class="p-6 transition-colors border border-gray-700 rounded-lg hover:border-gray-400 group"
|
|
1423
|
+
>
|
|
1424
|
+
<h2 class="mb-3 text-2xl font-semibold">
|
|
1425
|
+
Deploy
|
|
1426
|
+
<span class="inline-block transition-transform group-hover:translate-x-1">
|
|
1427
|
+
->
|
|
1428
|
+
</span>
|
|
1429
|
+
</h2>
|
|
1430
|
+
<p class="text-sm text-gray-400">
|
|
1431
|
+
Instantly deploy your NextPy site to a shareable URL with RahimStudios.
|
|
1432
|
+
</p>
|
|
1433
|
+
</a>
|
|
1418
1434
|
</div>
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
1435
|
</div>
|
|
1422
1436
|
)
|
|
1423
1437
|
|
|
1438
|
+
|
|
1424
1439
|
def getServerSideProps(context):
|
|
1425
1440
|
return {
|
|
1426
1441
|
"props": {
|
|
1427
|
-
"title": "
|
|
1428
|
-
"
|
|
1442
|
+
"title": "Welcome to NextPy!",
|
|
1443
|
+
"message": "Build amazing web apps with Python and True JSX"
|
|
1429
1444
|
}
|
|
1430
1445
|
}
|
|
1431
1446
|
|
|
1432
|
-
default = About
|
|
1433
|
-
'''
|
|
1434
|
-
)
|
|
1435
|
-
click.echo(" Created: pages/about.py (enhanced interactive page)")
|
|
1436
|
-
|
|
1437
|
-
# Create interactive demo pages
|
|
1438
|
-
(project_dir / "pages" / "interactive.py").write_text('''"""Interactive Demo Page"""
|
|
1439
1447
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
@component
|
|
1444
|
-
def InteractiveDemo(props=None):
|
|
1445
|
-
"""Interactive demo showcasing NextPy capabilities"""
|
|
1446
|
-
return (
|
|
1447
|
-
<div class="min-h-screen py-12 bg-gradient-to-br from-indigo-50 to-purple-100">
|
|
1448
|
-
<div class="px-4 mx-auto max-w-7xl sm:px-6 lg:px-8">
|
|
1449
|
-
<h1 class="mb-12 text-4xl font-extrabold text-center text-gray-900">
|
|
1450
|
-
Interactive NextPy Demos
|
|
1451
|
-
</h1>
|
|
1452
|
-
|
|
1453
|
-
<div class="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
|
1454
|
-
|
|
1455
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1456
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Live Counter</h2>
|
|
1457
|
-
<div class="text-center">
|
|
1458
|
-
<div class="mb-4 text-6xl font-bold text-blue-600" id="counter">0</div>
|
|
1459
|
-
<div class="space-x-4">
|
|
1460
|
-
<button onclick="updateCounter(-1)" class="px-6 py-3 text-white transition-colors bg-red-500 rounded-lg hover:bg-red-600">
|
|
1461
|
-
-
|
|
1462
|
-
</button>
|
|
1463
|
-
<button onclick="updateCounter(1)" class="px-6 py-3 text-white transition-colors bg-green-500 rounded-lg hover:bg-green-600">
|
|
1464
|
-
+
|
|
1465
|
-
</button>
|
|
1466
|
-
<button onclick="resetCounter()" class="px-6 py-3 text-white transition-colors bg-gray-500 rounded-lg hover:bg-gray-600">
|
|
1467
|
-
Reset
|
|
1468
|
-
</button>
|
|
1469
|
-
</div>
|
|
1470
|
-
</div>
|
|
1471
|
-
</div>
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1475
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Todo List</h2>
|
|
1476
|
-
<div class="space-y-4">
|
|
1477
|
-
<div class="flex space-x-2">
|
|
1478
|
-
<input type="text" id="todoInput" placeholder="Add a new todo..." class="flex-1 px-4 py-2 border border-gray-300 rounded-lg" />
|
|
1479
|
-
<button onclick="addTodo()" class="px-6 py-2 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
|
|
1480
|
-
Add
|
|
1481
|
-
</button>
|
|
1482
|
-
</div>
|
|
1483
|
-
<ul id="todoList" class="space-y-2">
|
|
1484
|
-
|
|
1485
|
-
</ul>
|
|
1486
|
-
</div>
|
|
1487
|
-
</div>
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1491
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Color Picker</h2>
|
|
1492
|
-
<div class="space-y-4">
|
|
1493
|
-
<input type="color" id="colorPicker" class="w-full h-20 rounded-lg cursor-pointer" />
|
|
1494
|
-
<div id="colorDisplay" class="p-4 font-mono text-lg text-center bg-gray-100 rounded-lg">
|
|
1495
|
-
Selected: #3B82F6
|
|
1496
|
-
</div>
|
|
1497
|
-
</div>
|
|
1498
|
-
</div>
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
<div class="p-6 bg-white shadow-lg rounded-xl">
|
|
1502
|
-
<h2 class="mb-4 text-2xl font-bold text-gray-900">Form Validation</h2>
|
|
1503
|
-
<form onsubmit="validateForm(event)" class="space-y-4">
|
|
1504
|
-
<div>
|
|
1505
|
-
<label class="block mb-2 text-sm font-medium text-gray-700">Email</label>
|
|
1506
|
-
<input type="email" id="email" required class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="you@example.com" />
|
|
1507
|
-
</div>
|
|
1508
|
-
<div>
|
|
1509
|
-
<label class="block mb-2 text-sm font-medium text-gray-700">Password</label>
|
|
1510
|
-
<input type="password" id="password" required minlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-lg" placeholder="•••••••••" />
|
|
1511
|
-
</div>
|
|
1512
|
-
<button type="submit" class="w-full px-6 py-3 text-white transition-colors bg-blue-500 rounded-lg hover:bg-blue-600">
|
|
1513
|
-
Validate & Submit
|
|
1514
|
-
</button>
|
|
1515
|
-
</form>
|
|
1516
|
-
<div id="validationResult" class="hidden p-4 mt-4 rounded-lg">
|
|
1517
|
-
|
|
1518
|
-
</div>
|
|
1519
|
-
</div>
|
|
1520
|
-
</div>
|
|
1521
|
-
</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
)
|
|
1448
|
+
default = Home
|
|
1524
1449
|
|
|
1525
|
-
def getServerSideProps(context):
|
|
1526
|
-
return {"props": {}}
|
|
1527
1450
|
|
|
1528
|
-
default = InteractiveDemo
|
|
1529
1451
|
''')
|
|
1530
|
-
click.echo(" Created: pages/
|
|
1452
|
+
click.echo(" Created: pages/index.py ")
|
|
1453
|
+
|
|
1531
1454
|
|
|
1532
1455
|
(project_dir / "components" / "ui" / "Button.py").write_text(
|
|
1533
1456
|
'''"""Button component"""
|
|
1534
|
-
from nextpy.psx import
|
|
1457
|
+
from nextpy.psx import psx
|
|
1458
|
+
|
|
1535
1459
|
|
|
1536
1460
|
|
|
1537
|
-
@component
|
|
1538
1461
|
def Button(props = None):
|
|
1539
1462
|
"""Reusable Button component"""
|
|
1540
1463
|
props = props or {}
|
|
@@ -1556,14 +1479,14 @@ def Button(props = None):
|
|
|
1556
1479
|
|
|
1557
1480
|
class_attr = f"px-6 py-3 rounded-lg font-medium transition-all duration-200 transform hover:scale-105 {variant_class} {className}"
|
|
1558
1481
|
|
|
1559
|
-
return (
|
|
1482
|
+
return psx(f"
|
|
1560
1483
|
<button class={class_attr}
|
|
1561
1484
|
id={props.get("id")}
|
|
1562
1485
|
disabled={props.get("disabled", False)}
|
|
1563
1486
|
onclick={props.get("onClick", "")}>
|
|
1564
1487
|
{children}
|
|
1565
1488
|
</button>
|
|
1566
|
-
)
|
|
1489
|
+
")
|
|
1567
1490
|
|
|
1568
1491
|
default = Button
|
|
1569
1492
|
'''
|
|
@@ -1613,119 +1536,7 @@ default = Layout
|
|
|
1613
1536
|
)
|
|
1614
1537
|
click.echo(" Created: components/layout/Layout.py")
|
|
1615
1538
|
|
|
1616
|
-
|
|
1617
|
-
(project_dir / ".vscode").mkdir(exist_ok=True)
|
|
1618
|
-
(project_dir / ".vscode" / "settings.json").write_text("""{
|
|
1619
|
-
"files.associations": {
|
|
1620
|
-
"*.py": "python",
|
|
1621
|
-
"*.py.jsx": "python",
|
|
1622
|
-
"*.jsx": "javascriptreact"
|
|
1623
|
-
},
|
|
1624
|
-
"emmet.includeLanguages": {
|
|
1625
|
-
"python": "html",
|
|
1626
|
-
"javascriptreact": "html",
|
|
1627
|
-
"typescriptreact": "html"
|
|
1628
|
-
},
|
|
1629
|
-
"emmet.triggerExpansionOnTab": true,
|
|
1630
|
-
"typescript.preferences.includePackageJsonAutoImports": "on",
|
|
1631
|
-
"editor.quickSuggestions": {
|
|
1632
|
-
"strings": true
|
|
1633
|
-
},
|
|
1634
|
-
"editor.suggestSelection": "first",
|
|
1635
|
-
"editor.wordBasedSuggestions": true,
|
|
1636
|
-
"editor.snippetSuggestions": "top",
|
|
1637
|
-
"editor.parameterHints": {
|
|
1638
|
-
"enabled": true
|
|
1639
|
-
},
|
|
1640
|
-
"editor.snippetSuggestions": "top",
|
|
1641
|
-
"html.autoClosingTags": true,
|
|
1642
|
-
"css.autoClosingTags": true,
|
|
1643
|
-
"javascript.autoClosingTags": true,
|
|
1644
|
-
"typescript.autoClosingTags": true,
|
|
1645
|
-
"editor.autoClosingBrackets": "always",
|
|
1646
|
-
"editor.autoClosingQuotes": "always",
|
|
1647
|
-
"editor.formatOnSave": true,
|
|
1648
|
-
"editor.codeActionsOnSave": {
|
|
1649
|
-
"source.fixAll.eslint": true,
|
|
1650
|
-
"source.organizeImports": true
|
|
1651
|
-
},
|
|
1652
|
-
"emmet.preferences": {
|
|
1653
|
-
"css.property.endWithSemicolon": true,
|
|
1654
|
-
"css.value.unit": "rem"
|
|
1655
|
-
},
|
|
1656
|
-
"files.exclude": {
|
|
1657
|
-
"*}__pycache__": true,
|
|
1658
|
-
"*}*.pyc": true,
|
|
1659
|
-
"*}node_modules": true,
|
|
1660
|
-
"*}out": true,
|
|
1661
|
-
"*}.next": true,
|
|
1662
|
-
"*}.pytest_cache": true,
|
|
1663
|
-
"*}.mypy_cache": true
|
|
1664
|
-
},
|
|
1665
|
-
"search.exclude": {
|
|
1666
|
-
"*}node_modules": true,
|
|
1667
|
-
"*}out": true,
|
|
1668
|
-
"*}.next": true,
|
|
1669
|
-
"*}__pycache__": true,
|
|
1670
|
-
"*}.pytest_cache": true,
|
|
1671
|
-
"*}.mypy_cache": true
|
|
1672
|
-
},
|
|
1673
|
-
"python.linting.enabled": true,
|
|
1674
|
-
"python.linting.pylintEnabled": false,
|
|
1675
|
-
"python.linting.flake8Enabled": false,
|
|
1676
|
-
"python.linting.pylintArgs": [
|
|
1677
|
-
"--disable=C0114,C0115,C0116,E1132,E1131,E1130"
|
|
1678
|
-
],
|
|
1679
|
-
"python.formatting.provider": "black",
|
|
1680
|
-
"[python]": {
|
|
1681
|
-
"editor.defaultFormatter": "ms-python.black-formatter",
|
|
1682
|
-
"editor.formatOnSave": true,
|
|
1683
|
-
"editor.rulers": [88],
|
|
1684
|
-
"editor.tabSize": 4,
|
|
1685
|
-
"editor.insertSpaces": true
|
|
1686
|
-
}
|
|
1687
|
-
}""")
|
|
1688
|
-
click.echo(" Created: .vscode/settings.json")
|
|
1689
|
-
|
|
1690
|
-
(project_dir / ".vscode" / "extensions.json").write_text("""{
|
|
1691
|
-
"recommendations": [
|
|
1692
|
-
"ms-python.python",
|
|
1693
|
-
"ms-python.vscode-pylance",
|
|
1694
|
-
"bradlc.vscode-tailwindcss",
|
|
1695
|
-
"esbenp.prettier-vscode",
|
|
1696
|
-
"ms-vscode.vscode-json",
|
|
1697
|
-
"formulahendry.auto-rename-tag",
|
|
1698
|
-
"christian-kohler.path-intellisense",
|
|
1699
|
-
"ms-vscode.vscode-html-css-class-completion",
|
|
1700
|
-
"ms-vscode.vscode-emmet",
|
|
1701
|
-
"ms-vscode.vscode-eslint",
|
|
1702
|
-
"dbaeumer.vscode-eslint",
|
|
1703
|
-
"ms-vscode.vscode-typescript-next",
|
|
1704
|
-
"ritwickdey.liveserver",
|
|
1705
|
-
"ms-vscode.vscode-jest",
|
|
1706
|
-
"esbenp.prettier-vscode",
|
|
1707
|
-
"streetsidesoftware.code-spell-checker",
|
|
1708
|
-
"gruntfuggly.todo-tree",
|
|
1709
|
-
"ms-vscode.vscode-git-graph",
|
|
1710
|
-
"eamodio.gitlens",
|
|
1711
|
-
"ms-vscode.vscode-docker",
|
|
1712
|
-
"ms-vscode.remote-explorer",
|
|
1713
|
-
"ms-vscode-remote.remote-containers",
|
|
1714
|
-
"ms-vscode.vscode-remote-wsl",
|
|
1715
|
-
"redhat.vscode-yaml",
|
|
1716
|
-
"ms-vscode.vscode-markdown",
|
|
1717
|
-
"yzhang.markdown-all-in-one",
|
|
1718
|
-
"shd101wyy.markdown-preview-enhanced",
|
|
1719
|
-
"ms-vscode.vscode-python",
|
|
1720
|
-
"kevinrose.vsc-python-indent",
|
|
1721
|
-
"ms-python.black-formatter",
|
|
1722
|
-
"ms-python.isort",
|
|
1723
|
-
"ms-python.flake8",
|
|
1724
|
-
"ms-python.mypy-type-checker"
|
|
1725
|
-
]
|
|
1726
|
-
}""")
|
|
1727
|
-
click.echo(" Created: .vscode/extensions.json")
|
|
1728
|
-
|
|
1539
|
+
|
|
1729
1540
|
# Create comprehensive API examples
|
|
1730
1541
|
(project_dir / "pages" / "api" / "hello.py").write_text(
|
|
1731
1542
|
'''"""API example - Hello endpoint"""
|
|
@@ -2208,77 +2019,6 @@ Thumbs.db
|
|
|
2208
2019
|
''')
|
|
2209
2020
|
click.echo(" Created: .gitignore")
|
|
2210
2021
|
|
|
2211
|
-
# Create main.py with Tailwind compilation (for pip-installed NextPy)
|
|
2212
|
-
(project_dir / "main.py").write_text('''"""NextPy ASGI Application Entry Point"""
|
|
2213
|
-
|
|
2214
|
-
import os
|
|
2215
|
-
import sys
|
|
2216
|
-
import subprocess
|
|
2217
|
-
from pathlib import Path
|
|
2218
|
-
|
|
2219
|
-
try:
|
|
2220
|
-
print("Compiling Tailwind CSS...")
|
|
2221
|
-
proj_root = Path.cwd()
|
|
2222
|
-
framework_dir = Path(__file__).parent
|
|
2223
|
-
# If the project root doesn't have a styles.css yet, warn the user and create a minimal one.
|
|
2224
|
-
styles_file = proj_root / "styles.css"
|
|
2225
|
-
if not styles_file.exists():
|
|
2226
|
-
print("Warning: styles.css not found, creating a minimal file.")
|
|
2227
|
-
styles_file.write_text("@tailwind base;\n@tailwind components;\n@tailwind utilities;\n")
|
|
2228
|
-
|
|
2229
|
-
import shutil
|
|
2230
|
-
npm_bin = shutil.which("npm")
|
|
2231
|
-
if not npm_bin:
|
|
2232
|
-
raise FileNotFoundError("npm not found on PATH")
|
|
2233
|
-
|
|
2234
|
-
lockfile = framework_dir / "package-lock.json"
|
|
2235
|
-
node_modules = framework_dir / "node_modules"
|
|
2236
|
-
if not node_modules.exists():
|
|
2237
|
-
if lockfile.exists():
|
|
2238
|
-
subprocess.run([npm_bin, "ci"], cwd=str(framework_dir), check=True)
|
|
2239
|
-
else:
|
|
2240
|
-
subprocess.run([npm_bin, "install"], cwd=str(framework_dir), check=True)
|
|
2241
|
-
|
|
2242
|
-
subprocess.run([npm_bin, "run", "build:tailwind"], cwd=str(framework_dir), check=True)
|
|
2243
|
-
print("Tailwind CSS compiled successfully.")
|
|
2244
|
-
except subprocess.CalledProcessError as e:
|
|
2245
|
-
print(f"Error compiling Tailwind CSS: {e}")
|
|
2246
|
-
print("You can also run `cd .nextpy_framework/nextpy && npm ci && npm run build:tailwind` manually.")
|
|
2247
|
-
except FileNotFoundError:
|
|
2248
|
-
print("Error: npm not found. Make sure Node.js is installed and available on PATH.")
|
|
2249
|
-
print("See https://nodejs.org/ for installation instructions.")
|
|
2250
|
-
|
|
2251
|
-
# Import NextPy modules (works when installed via pip)
|
|
2252
|
-
from nextpy.server.app import create_app
|
|
2253
|
-
from nextpy.db import init_db
|
|
2254
|
-
from nextpy.config import settings
|
|
2255
|
-
|
|
2256
|
-
# Initialize database
|
|
2257
|
-
try:
|
|
2258
|
-
init_db(settings["database_url"])
|
|
2259
|
-
print("Database initialized successfully.")
|
|
2260
|
-
except Exception as e:
|
|
2261
|
-
print(f"Warning: Database initialization failed: {e}")
|
|
2262
|
-
|
|
2263
|
-
# Create NextPy app with file-based routing
|
|
2264
|
-
app = create_app(
|
|
2265
|
-
pages_dir="pages",
|
|
2266
|
-
templates_dir="templates",
|
|
2267
|
-
public_dir="public",
|
|
2268
|
-
out_dir="out",
|
|
2269
|
-
debug=settings["debug"],
|
|
2270
|
-
)
|
|
2271
|
-
|
|
2272
|
-
# Note: Routes are automatically loaded from pages/ directory
|
|
2273
|
-
# - / -> pages/index.py
|
|
2274
|
-
# - /about -> pages/about.py
|
|
2275
|
-
# - /api/* -> pages/api/*.py
|
|
2276
|
-
|
|
2277
|
-
if __name__ == "__main__":
|
|
2278
|
-
import uvicorn
|
|
2279
|
-
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
|
2280
|
-
''')
|
|
2281
|
-
click.echo(" Created: main.py (pip-compatible)")
|
|
2282
2022
|
|
|
2283
2023
|
# Create .env file for development
|
|
2284
2024
|
(project_dir / ".env").write_text("""# NextPy Development Environment
|
|
@@ -243,7 +243,7 @@ class ComponentRenderer:
|
|
|
243
243
|
elif has_interactive_decorator and not hasattr(component, '__wrapped__'):
|
|
244
244
|
# The original file had @interactive_component but the decorator wasn't applied
|
|
245
245
|
# This means we need to apply the decorator to the rendered HTML
|
|
246
|
-
html = self._apply_interactive_component_to_rendered_html(rendered, original_content, page_props)
|
|
246
|
+
html = self._apply_interactive_component_to_rendered_html(file_path, rendered, original_content, page_props)
|
|
247
247
|
else:
|
|
248
248
|
# Convert to HTML, passing page props as context for {expressions}
|
|
249
249
|
# Check if this is a PSX component and handle Server/Client components
|
|
@@ -320,9 +320,20 @@ class ComponentRenderer:
|
|
|
320
320
|
|
|
321
321
|
# 🔥 Inject Dev Tools (only in dev mode)
|
|
322
322
|
dev_scripts = ""
|
|
323
|
+
|
|
324
|
+
# Ensure the Action runtime is always available on the page.
|
|
325
|
+
# Your button onclick handlers expect window.NextPyActionRuntime.
|
|
326
|
+
action_runtime_script = ""
|
|
327
|
+
try:
|
|
328
|
+
from ..psx.runtime.js_actions_runtime import JS_ACTION_RUNTIME_SCRIPT
|
|
329
|
+
action_runtime_script = f"<script>{JS_ACTION_RUNTIME_SCRIPT}</script>\n"
|
|
330
|
+
except ImportError:
|
|
331
|
+
action_runtime_script = ""
|
|
332
|
+
|
|
323
333
|
if dev_mode:
|
|
324
334
|
dev_scripts = """
|
|
325
335
|
<script>
|
|
336
|
+
|
|
326
337
|
/* ===============================
|
|
327
338
|
NextPy Live Error Overlay
|
|
328
339
|
================================ */
|
|
@@ -581,14 +592,7 @@ class ComponentRenderer:
|
|
|
581
592
|
|
|
582
593
|
<link rel="stylesheet" href="./public/tailwind.css">
|
|
583
594
|
|
|
584
|
-
|
|
585
|
-
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
|
|
586
|
-
|
|
587
|
-
body {{
|
|
588
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
589
|
-
|
|
590
|
-
}}
|
|
591
|
-
</style>
|
|
595
|
+
|
|
592
596
|
|
|
593
597
|
</head>
|
|
594
598
|
|
|
@@ -598,11 +602,12 @@ class ComponentRenderer:
|
|
|
598
602
|
{content}
|
|
599
603
|
</div>
|
|
600
604
|
|
|
601
|
-
{dev_scripts}
|
|
605
|
+
{action_runtime_script}{dev_scripts}
|
|
602
606
|
|
|
603
607
|
</body>
|
|
604
608
|
</html>
|
|
605
609
|
"""
|
|
610
|
+
|
|
606
611
|
|
|
607
612
|
|
|
608
613
|
|
|
@@ -895,6 +900,8 @@ class ComponentRenderer:
|
|
|
895
900
|
# Extract handlers from the original content
|
|
896
901
|
handlers = extract_handler_functions(lambda: None) # We'll parse the content directly
|
|
897
902
|
|
|
903
|
+
print(f"new keys {handlers}")
|
|
904
|
+
|
|
898
905
|
# Parse the original content to find handler functions
|
|
899
906
|
import re
|
|
900
907
|
handler_pattern = r'def\s+(\w+)\s*\([^)]*\)\s*:'
|
|
@@ -933,6 +940,7 @@ class ComponentRenderer:
|
|
|
933
940
|
# Extract state keys
|
|
934
941
|
state_pattern = r'\[(\w+),\s*set\w+\]\s*=\s*useState'
|
|
935
942
|
state_keys = re.findall(state_pattern, original_content)
|
|
943
|
+
print(f"here new keys {state_keys}")
|
|
936
944
|
|
|
937
945
|
# Convert handler attributes in HTML
|
|
938
946
|
html_with_handlers = convert_handler_attributes_in_html(rendered_html, handlers, state_keys)
|
|
@@ -957,7 +965,7 @@ class ComponentRenderer:
|
|
|
957
965
|
|
|
958
966
|
# Generate scripts
|
|
959
967
|
full_script = engine.generate_hydration_script()
|
|
960
|
-
handler_script = generate_handler_registration_script(handlers, component_id, state_keys=state_keys)
|
|
968
|
+
handler_script = generate_handler_registration_script(handlers, component_id, state_keys=state_keys, html=html_with_handlers)
|
|
961
969
|
hydrator = get_component_hydrator()
|
|
962
970
|
hydration_script = hydrator.generate_hydration_script()
|
|
963
971
|
|