pyxflow 0.4.0__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.
- pyxflow/__init__.py +11 -0
- pyxflow/app.py +536 -0
- pyxflow/bundle/VAADIN/build/FlowBootstrap-tpaNq9i9.js +3 -0
- pyxflow/bundle/VAADIN/build/FlowBootstrap-tpaNq9i9.js.br +0 -0
- pyxflow/bundle/VAADIN/build/FlowClient-BJ9ZfTZb.js +3 -0
- pyxflow/bundle/VAADIN/build/FlowClient-BJ9ZfTZb.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-BSat8ge4.js +1646 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-BSat8ge4.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-B_vo-znS.js +1646 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-B_vo-znS.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-DW726K0S.js +1646 -0
- pyxflow/bundle/VAADIN/build/chunk-20b5913756ce3aca167f0ba08695a16bf3b2ced2aa3d79a2a3799bc94e649650-DW726K0S.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-A_pwI8nt.js +507 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-A_pwI8nt.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-BA7ReY0z.js +507 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-BA7ReY0z.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-Dw4NGPaD.js +507 -0
- pyxflow/bundle/VAADIN/build/chunk-3cf1c80c42b2c95b3d2b91b4d1432902255060706be2252df851b542cc34ffc5-Dw4NGPaD.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-BHlSfVe4.js +1843 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-BHlSfVe4.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-D8CLzUCc.js +1843 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-D8CLzUCc.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-R5VHaiul.js +1843 -0
- pyxflow/bundle/VAADIN/build/chunk-7e3dc433ae4599f705db307c09bf7a8ba9e18853c089e7754783c59f030922e9-R5VHaiul.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-CUp7QPlV.js +58 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-CUp7QPlV.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-CyOyikW_.js +58 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-CyOyikW_.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-DKkIdWLP.js +58 -0
- pyxflow/bundle/VAADIN/build/chunk-c8efc5a648d42f293847c817a5dddab3643111e0d94b848c89e3087c602cc885-DKkIdWLP.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-BBknl1Er.js +1079 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-BBknl1Er.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-BEZ1SplM.js +1079 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-BEZ1SplM.js.br +0 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-Bl2cj9us.js +1079 -0
- pyxflow/bundle/VAADIN/build/chunk-df82228a0d0ba7f82937da4dff5549a7886e68d794f21c59836b0708d2669a75-Bl2cj9us.js.br +0 -0
- pyxflow/bundle/VAADIN/build/commonjsHelpers-CqkleIqs.js +1 -0
- pyxflow/bundle/VAADIN/build/commonjsHelpers-CqkleIqs.js.br +0 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-A_cbqzPb.js +12141 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-A_cbqzPb.js.br +0 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-BNGvL9My.js +12141 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-BNGvL9My.js.br +0 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-BkytpRbC.js +12141 -0
- pyxflow/bundle/VAADIN/build/generated-flow-imports-BkytpRbC.js.br +0 -0
- pyxflow/bundle/VAADIN/build/indexhtml-0Ske2WDa.js +273 -0
- pyxflow/bundle/VAADIN/build/indexhtml-0Ske2WDa.js.br +0 -0
- pyxflow/bundle/VAADIN/build/indexhtml-C5Ngnva6.js +273 -0
- pyxflow/bundle/VAADIN/build/indexhtml-C5Ngnva6.js.br +0 -0
- pyxflow/bundle/VAADIN/build/indexhtml-GL0WLVAv.js +273 -0
- pyxflow/bundle/VAADIN/build/indexhtml-GL0WLVAv.js.br +0 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-BXNKwFyY.js +642 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-BXNKwFyY.js.br +0 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-CG0RSisR.js +642 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-CG0RSisR.js.br +0 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-DFH06Ogz.js +642 -0
- pyxflow/bundle/VAADIN/build/vaadin-iconset-DFH06Ogz.js.br +0 -0
- pyxflow/bundle/VAADIN/static/push/vaadinPush-min.js +1 -0
- pyxflow/bundle/VAADIN/static/push/vaadinPush-min.js.gz +0 -0
- pyxflow/bundle/VAADIN/static/push/vaadinPush.js +3508 -0
- pyxflow/bundle/VAADIN/static/push/vaadinPush.js.gz +0 -0
- pyxflow/bundle/aura/aura.css +3 -0
- pyxflow/bundle/aura/fonts/InstrumentSans/InstrumentSans.woff2 +0 -0
- pyxflow/bundle/index.html +25 -0
- pyxflow/bundle/index.html.br +0 -0
- pyxflow/bundle/lumo/lumo.css +55 -0
- pyxflow/bundle/lumo/presets/compact.css +1 -0
- pyxflow/bundle/lumo/utility.css +1 -0
- pyxflow/bundle/pwa-icons/icons/icon-1125x2436.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1136x640.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1170x2532.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1242x2208.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1242x2688.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1284x2778.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1334x750.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-144x144.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1536x2048.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1620x2160.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1668x2224.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1668x2388.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-16x16.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-1792x828.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-180x180.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-192x192.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2048x1536.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2048x2732.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2160x1620.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2208x1242.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2224x1668.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2388x1668.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2436x1125.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2532x1170.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2688x1242.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2732x2048.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-2778x1284.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-32x32.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-512x512.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-640x1136.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-750x1334.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-828x1792.png +0 -0
- pyxflow/bundle/pwa-icons/icons/icon-96x96.png +0 -0
- pyxflow/bundle/sw.js +2 -0
- pyxflow/bundle/sw.js.br +0 -0
- pyxflow/bundle_generator.py +658 -0
- pyxflow/bundle_generator_resources/.mvn/wrapper/maven-wrapper.properties +3 -0
- pyxflow/bundle_generator_resources/mvnw +295 -0
- pyxflow/bundle_generator_resources/mvnw.cmd +189 -0
- pyxflow/components/__init__.py +255 -0
- pyxflow/components/accordion.py +143 -0
- pyxflow/components/app_layout.py +123 -0
- pyxflow/components/avatar.py +166 -0
- pyxflow/components/button.py +150 -0
- pyxflow/components/card.py +188 -0
- pyxflow/components/checkbox.py +114 -0
- pyxflow/components/checkbox_group.py +170 -0
- pyxflow/components/combo_box.py +372 -0
- pyxflow/components/confirm_dialog.py +278 -0
- pyxflow/components/constants.py +618 -0
- pyxflow/components/context_menu.py +276 -0
- pyxflow/components/custom_field.py +121 -0
- pyxflow/components/date_picker.py +216 -0
- pyxflow/components/date_time_picker.py +186 -0
- pyxflow/components/details.py +156 -0
- pyxflow/components/dialog.py +453 -0
- pyxflow/components/drawer_toggle.py +10 -0
- pyxflow/components/email_field.py +178 -0
- pyxflow/components/flex_layout.py +236 -0
- pyxflow/components/form_layout.py +421 -0
- pyxflow/components/grid.py +1839 -0
- pyxflow/components/horizontal_layout.py +197 -0
- pyxflow/components/html.py +256 -0
- pyxflow/components/icon.py +55 -0
- pyxflow/components/list_box.py +284 -0
- pyxflow/components/login.py +237 -0
- pyxflow/components/markdown.py +38 -0
- pyxflow/components/master_detail_layout.py +302 -0
- pyxflow/components/menu_bar.py +338 -0
- pyxflow/components/message_input.py +64 -0
- pyxflow/components/message_list.py +108 -0
- pyxflow/components/mixins.py +88 -0
- pyxflow/components/multi_select_combo_box.py +343 -0
- pyxflow/components/notification.py +339 -0
- pyxflow/components/number_field.py +295 -0
- pyxflow/components/password_field.py +177 -0
- pyxflow/components/popover.py +288 -0
- pyxflow/components/progress_bar.py +82 -0
- pyxflow/components/radio_button_group.py +149 -0
- pyxflow/components/renderer.py +76 -0
- pyxflow/components/router_link.py +55 -0
- pyxflow/components/scroller.py +91 -0
- pyxflow/components/select.py +263 -0
- pyxflow/components/side_nav.py +226 -0
- pyxflow/components/span.py +44 -0
- pyxflow/components/split_layout.py +181 -0
- pyxflow/components/tab_sheet.py +152 -0
- pyxflow/components/tabs.py +255 -0
- pyxflow/components/text_area.py +192 -0
- pyxflow/components/text_field.py +238 -0
- pyxflow/components/time_picker.py +201 -0
- pyxflow/components/upload.py +280 -0
- pyxflow/components/value_change_mode.py +5 -0
- pyxflow/components/vertical_layout.py +194 -0
- pyxflow/components/virtual_list.py +234 -0
- pyxflow/core/__init__.py +9 -0
- pyxflow/core/component.py +794 -0
- pyxflow/core/element.py +130 -0
- pyxflow/core/keys.py +34 -0
- pyxflow/core/state_node.py +121 -0
- pyxflow/core/state_tree.py +127 -0
- pyxflow/data/__init__.py +47 -0
- pyxflow/data/binder.py +382 -0
- pyxflow/data/converter.py +51 -0
- pyxflow/data/provider.py +191 -0
- pyxflow/data/result.py +78 -0
- pyxflow/data/validator.py +89 -0
- pyxflow/menu.py +130 -0
- pyxflow/router.py +674 -0
- pyxflow/scaffold/favicon.ico +0 -0
- pyxflow/scaffold/project/__main__.py.tmpl +5 -0
- pyxflow/scaffold/project/static/styles/styles.css +8 -0
- pyxflow/scaffold/project/views/hello_world.py.tmpl +15 -0
- pyxflow/scaffold/project/views/main_layout.py.tmpl +17 -0
- pyxflow/scaffold/vscode/extensions.json +7 -0
- pyxflow/scaffold/vscode/python.code-snippets +22 -0
- pyxflow/scaffold/vscode/settings.json +48 -0
- pyxflow/scaffold/vscode/templates/pyxflow_view.py +10 -0
- pyxflow/server/__init__.py +6 -0
- pyxflow/server/http_server.py +820 -0
- pyxflow/server/uidl_handler.py +1099 -0
- pyxflow-0.4.0.dist-info/METADATA +281 -0
- pyxflow-0.4.0.dist-info/RECORD +193 -0
- pyxflow-0.4.0.dist-info/WHEEL +4 -0
- pyxflow-0.4.0.dist-info/entry_points.txt +3 -0
- pyxflow-0.4.0.dist-info/licenses/LICENSE +191 -0
pyxflow/__init__.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Vaadin Flow for Python - Server-side UI framework."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.4.0"
|
|
4
|
+
|
|
5
|
+
from pyxflow.core.component import Component
|
|
6
|
+
from pyxflow.core.element import Element
|
|
7
|
+
from pyxflow.router import AppShell, BeforeEnterEvent, ColorScheme, Location, Push, QueryParameters, Route, RouteAlias, RouteParameters, PageTitle, StyleSheet, discover_views
|
|
8
|
+
from pyxflow.menu import Menu, MenuEntry, get_menu_entries, get_page_header
|
|
9
|
+
from pyxflow.app import FlowApp
|
|
10
|
+
|
|
11
|
+
__all__ = ["AppShell", "BeforeEnterEvent", "ColorScheme", "Component", "Element", "FlowApp", "Location", "Menu", "MenuEntry", "PageTitle", "Push", "QueryParameters", "Route", "RouteAlias", "RouteParameters", "StyleSheet", "discover_views", "get_menu_entries", "get_page_header", "__version__"]
|
pyxflow/app.py
ADDED
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
"""FlowApp — single entry point to configure and run a PyXFlow application."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FlowApp:
|
|
10
|
+
"""Configure and run a PyXFlow application.
|
|
11
|
+
|
|
12
|
+
Usage::
|
|
13
|
+
|
|
14
|
+
# demo/__main__.py
|
|
15
|
+
from pyxflow import FlowApp
|
|
16
|
+
|
|
17
|
+
FlowApp(port=8088).run()
|
|
18
|
+
|
|
19
|
+
CLI flags:
|
|
20
|
+
--dev Auto-reload on source changes (requires watchfiles)
|
|
21
|
+
--debug Verbose UIDL protocol logging
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *, port: int = 8080, host: str = "localhost"):
|
|
25
|
+
# Auto-detect caller's package → views module
|
|
26
|
+
frame = inspect.stack()[1]
|
|
27
|
+
module_name = frame.frame.f_globals.get("__name__", "")
|
|
28
|
+
if module_name == "__main__":
|
|
29
|
+
# python -m <package> → resolve from __spec__ or file path
|
|
30
|
+
spec = frame.frame.f_globals.get("__spec__")
|
|
31
|
+
if spec and spec.parent:
|
|
32
|
+
package = spec.parent
|
|
33
|
+
else:
|
|
34
|
+
# Fallback: derive from file path (e.g. demo/__main__.py → demo)
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
caller_path = Path(frame.filename).resolve()
|
|
37
|
+
package = caller_path.parent.name
|
|
38
|
+
elif "." in module_name:
|
|
39
|
+
package = module_name.rsplit(".", 1)[0]
|
|
40
|
+
else:
|
|
41
|
+
package = module_name
|
|
42
|
+
self._views = f"{package}.views"
|
|
43
|
+
self._port = port
|
|
44
|
+
self._host = host
|
|
45
|
+
|
|
46
|
+
def run(self):
|
|
47
|
+
"""Parse CLI flags and start the server."""
|
|
48
|
+
args = set(sys.argv[1:])
|
|
49
|
+
dev = "--dev" in args
|
|
50
|
+
debug = "--debug" in args
|
|
51
|
+
|
|
52
|
+
if dev:
|
|
53
|
+
self._run_dev(debug)
|
|
54
|
+
else:
|
|
55
|
+
_serve(self._views, self._host, self._port, debug, dev=False)
|
|
56
|
+
|
|
57
|
+
def _run_dev(self, debug: bool):
|
|
58
|
+
"""Dev mode: parent owns the socket, children are restarted on changes.
|
|
59
|
+
|
|
60
|
+
The listening socket is created once in this parent process and
|
|
61
|
+
inherited by each child via pass_fds. When a child is killed for
|
|
62
|
+
reload, the socket stays open — no EADDRINUSE race.
|
|
63
|
+
"""
|
|
64
|
+
import socket
|
|
65
|
+
import subprocess
|
|
66
|
+
import watchfiles
|
|
67
|
+
from pathlib import Path
|
|
68
|
+
|
|
69
|
+
watch_dir = Path(".").resolve()
|
|
70
|
+
print(f" Dev mode: watching {watch_dir} for Python file changes", flush=True)
|
|
71
|
+
|
|
72
|
+
# Check if something is already listening on the port
|
|
73
|
+
probe = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
74
|
+
try:
|
|
75
|
+
probe.connect((self._host, self._port))
|
|
76
|
+
probe.close()
|
|
77
|
+
print(f"\n ERROR: Port {self._port} is already in use.")
|
|
78
|
+
print(f" Kill the other process: lsof -ti :{self._port} | xargs kill -9\n")
|
|
79
|
+
return
|
|
80
|
+
except ConnectionRefusedError:
|
|
81
|
+
pass # Nothing listening — good
|
|
82
|
+
finally:
|
|
83
|
+
probe.close()
|
|
84
|
+
|
|
85
|
+
# Create listening socket in the parent — survives child restarts
|
|
86
|
+
srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
87
|
+
srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
88
|
+
srv_sock.bind((self._host, self._port))
|
|
89
|
+
srv_sock.listen(128)
|
|
90
|
+
srv_sock.set_inheritable(True)
|
|
91
|
+
fd = srv_sock.fileno()
|
|
92
|
+
print(f" Listening on http://{self._host}:{self._port}", flush=True)
|
|
93
|
+
|
|
94
|
+
env = os.environ.copy()
|
|
95
|
+
env["_PYFLOW_APP"] = json.dumps({
|
|
96
|
+
"views": self._views,
|
|
97
|
+
"host": self._host,
|
|
98
|
+
"port": self._port,
|
|
99
|
+
"debug": debug,
|
|
100
|
+
"socket_fd": fd,
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
def start_child():
|
|
104
|
+
return subprocess.Popen(
|
|
105
|
+
[sys.executable, "-c",
|
|
106
|
+
"from pyxflow.app import _dev_serve; _dev_serve()"],
|
|
107
|
+
pass_fds=(fd,),
|
|
108
|
+
env=env,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def stop_child(proc):
|
|
112
|
+
if proc.poll() is None:
|
|
113
|
+
proc.kill()
|
|
114
|
+
proc.wait(timeout=2)
|
|
115
|
+
|
|
116
|
+
# Track mtimes to ignore metadata-only events (macOS FSEvents
|
|
117
|
+
# fires for extended attribute changes like "last opened date")
|
|
118
|
+
file_mtimes: dict[str, float] = {}
|
|
119
|
+
|
|
120
|
+
proc = start_child()
|
|
121
|
+
try:
|
|
122
|
+
for changes in watchfiles.watch(
|
|
123
|
+
".",
|
|
124
|
+
watch_filter=watchfiles.PythonFilter(),
|
|
125
|
+
debounce=800,
|
|
126
|
+
):
|
|
127
|
+
actually_changed = []
|
|
128
|
+
for _, p in changes:
|
|
129
|
+
try:
|
|
130
|
+
mtime = os.path.getmtime(p)
|
|
131
|
+
except OSError:
|
|
132
|
+
mtime = 0
|
|
133
|
+
if file_mtimes.get(p) != mtime:
|
|
134
|
+
file_mtimes[p] = mtime
|
|
135
|
+
actually_changed.append(os.path.relpath(p, watch_dir))
|
|
136
|
+
if not actually_changed:
|
|
137
|
+
continue
|
|
138
|
+
paths = sorted(actually_changed)
|
|
139
|
+
print(f" Reloading because files modified: {', '.join(paths)}", flush=True)
|
|
140
|
+
stop_child(proc)
|
|
141
|
+
proc = start_child()
|
|
142
|
+
except KeyboardInterrupt:
|
|
143
|
+
pass
|
|
144
|
+
finally:
|
|
145
|
+
stop_child(proc)
|
|
146
|
+
srv_sock.close()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _auto_detect_app() -> str | None:
|
|
150
|
+
"""Try to find an app module in cwd by looking for <pkg>/views/ or ./views/."""
|
|
151
|
+
from pathlib import Path
|
|
152
|
+
# Check subdirectories first (e.g. myapp/views/)
|
|
153
|
+
for entry in sorted(Path.cwd().iterdir()):
|
|
154
|
+
if entry.is_dir() and (entry / "views").is_dir():
|
|
155
|
+
return entry.name
|
|
156
|
+
# Check cwd itself (e.g. views/ at root, from --setup without name)
|
|
157
|
+
if (Path.cwd() / "views").is_dir():
|
|
158
|
+
return Path.cwd().name.replace("-", "_")
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def _usage() -> None:
|
|
163
|
+
print("Usage: pyxflow [app_module] [--dev] [--debug] [--port PORT] [--host HOST]")
|
|
164
|
+
print(" pyxflow [app_module] bundle [--copy|--build] [--vaadin-version VERSION]")
|
|
165
|
+
print(" pyxflow --vscode")
|
|
166
|
+
print(" pyxflow --setup [app_name]")
|
|
167
|
+
print()
|
|
168
|
+
print(" app_module Python module with views (auto-detected if omitted)")
|
|
169
|
+
print(" --dev Auto-reload on source changes")
|
|
170
|
+
print(" --debug Verbose UIDL protocol logging")
|
|
171
|
+
print(" --port N Server port (default: 8080)")
|
|
172
|
+
print(" --host H Server host (default: localhost)")
|
|
173
|
+
print(" bundle Generate frontend bundle")
|
|
174
|
+
print(" --copy Copy bundle from Maven JARs in ~/.m2 (default, fast)")
|
|
175
|
+
print(" --build Full Maven build (slower, generates custom bundle)")
|
|
176
|
+
print(" --keep Keep bundle-project/ after build (only with --build)")
|
|
177
|
+
print(" --optimized Use optimized bundle (code-split chunks, larger on disk)")
|
|
178
|
+
print(" --vscode Generate .vscode/ config and install recommended extensions")
|
|
179
|
+
print(" --setup Scaffold a new Vaadin PyXFlow project (views, static, __main__.py)")
|
|
180
|
+
sys.exit(0)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _scaffold_dir():
|
|
184
|
+
"""Return the scaffold resource directory."""
|
|
185
|
+
import importlib.resources
|
|
186
|
+
return importlib.resources.files("pyxflow") / "scaffold"
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _setup_project(app_name: str | None = None) -> None:
|
|
190
|
+
"""Scaffold a new Vaadin PyXFlow project structure."""
|
|
191
|
+
import shutil
|
|
192
|
+
from pathlib import Path
|
|
193
|
+
|
|
194
|
+
root = Path.cwd()
|
|
195
|
+
if app_name is not None:
|
|
196
|
+
# Explicit name: create as subdirectory
|
|
197
|
+
pkg = root / app_name
|
|
198
|
+
else:
|
|
199
|
+
# No name: scaffold in cwd, derive name from directory
|
|
200
|
+
app_name = root.name.replace("-", "_")
|
|
201
|
+
pkg = root
|
|
202
|
+
scaffold = _scaffold_dir() / "project"
|
|
203
|
+
|
|
204
|
+
# --- Package directories ---
|
|
205
|
+
views_dir = pkg / "views"
|
|
206
|
+
static_styles = pkg / "static" / "styles"
|
|
207
|
+
static_images = pkg / "static" / "images"
|
|
208
|
+
|
|
209
|
+
for d in (views_dir, static_styles, static_images):
|
|
210
|
+
d.mkdir(parents=True, exist_ok=True)
|
|
211
|
+
|
|
212
|
+
def _write(path: Path, content: str) -> None:
|
|
213
|
+
action = "Updated" if path.exists() else "Created"
|
|
214
|
+
path.write_text(content)
|
|
215
|
+
print(f" {action} {path.relative_to(root)}")
|
|
216
|
+
|
|
217
|
+
def _write_template(src_name: str, dest: Path) -> None:
|
|
218
|
+
"""Read a .tmpl file from scaffold, replace {{app_name}}, write to dest."""
|
|
219
|
+
if dest.exists():
|
|
220
|
+
return
|
|
221
|
+
text = (scaffold / src_name).read_text()
|
|
222
|
+
if pkg == root:
|
|
223
|
+
# cwd mode: "from views.main_layout" not "from pepe.views.main_layout"
|
|
224
|
+
text = text.replace("{{app_name}}.", "")
|
|
225
|
+
text = text.replace("{{app_name}}", app_name)
|
|
226
|
+
_write(dest, text)
|
|
227
|
+
|
|
228
|
+
# --- __init__.py ---
|
|
229
|
+
for init in (pkg / "__init__.py", views_dir / "__init__.py"):
|
|
230
|
+
if not init.exists():
|
|
231
|
+
_write(init, "")
|
|
232
|
+
|
|
233
|
+
# --- Templated files ---
|
|
234
|
+
_write_template("__main__.py.tmpl", pkg / "__main__.py")
|
|
235
|
+
_write_template("views/main_layout.py.tmpl", views_dir / "main_layout.py")
|
|
236
|
+
_write_template("views/hello_world.py.tmpl", views_dir / "hello_world.py")
|
|
237
|
+
|
|
238
|
+
# --- Static files (copy as-is) ---
|
|
239
|
+
css_dest = static_styles / "styles.css"
|
|
240
|
+
if not css_dest.exists():
|
|
241
|
+
text = (scaffold / "static" / "styles" / "styles.css").read_text()
|
|
242
|
+
_write(css_dest, text)
|
|
243
|
+
|
|
244
|
+
# --- favicon.ico (binary copy) ---
|
|
245
|
+
favicon_dest = pkg / "static" / "favicon.ico"
|
|
246
|
+
if not favicon_dest.exists():
|
|
247
|
+
try:
|
|
248
|
+
import importlib.resources
|
|
249
|
+
favicon_src = _scaffold_dir() / "favicon.ico"
|
|
250
|
+
with importlib.resources.as_file(favicon_src) as src:
|
|
251
|
+
shutil.copy2(src, favicon_dest)
|
|
252
|
+
print(f" Created {favicon_dest.relative_to(root)}")
|
|
253
|
+
except (FileNotFoundError, TypeError):
|
|
254
|
+
print(" Warning: favicon.ico not found in package scaffold")
|
|
255
|
+
|
|
256
|
+
print(f"\n Project '{app_name}' scaffolded!")
|
|
257
|
+
if pkg == root:
|
|
258
|
+
print(f" Run: cd .. && python -m {app_name}")
|
|
259
|
+
else:
|
|
260
|
+
print(f" Run: python -m {app_name}")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _setup_vscode() -> None:
|
|
264
|
+
"""Generate .vscode/ config for Vaadin PyXFlow development."""
|
|
265
|
+
import shutil
|
|
266
|
+
import subprocess
|
|
267
|
+
from pathlib import Path
|
|
268
|
+
|
|
269
|
+
scaffold = _scaffold_dir() / "vscode"
|
|
270
|
+
vscode_dir = Path.cwd() / ".vscode"
|
|
271
|
+
vscode_dir.mkdir(exist_ok=True)
|
|
272
|
+
|
|
273
|
+
def _rel(path: Path) -> str:
|
|
274
|
+
return str(path.relative_to(Path.cwd()))
|
|
275
|
+
|
|
276
|
+
# --- settings.json (merge, don't overwrite) ---
|
|
277
|
+
settings_path = vscode_dir / "settings.json"
|
|
278
|
+
defaults = json.loads((scaffold / "settings.json").read_text())
|
|
279
|
+
if settings_path.exists():
|
|
280
|
+
existing = json.loads(settings_path.read_text())
|
|
281
|
+
for key, val in defaults.items():
|
|
282
|
+
if key not in existing:
|
|
283
|
+
existing[key] = val
|
|
284
|
+
settings_path.write_text(json.dumps(existing, indent=4) + "\n")
|
|
285
|
+
print(f" Updated {_rel(settings_path)}")
|
|
286
|
+
else:
|
|
287
|
+
settings_path.write_text(json.dumps(defaults, indent=4) + "\n")
|
|
288
|
+
print(f" Created {_rel(settings_path)}")
|
|
289
|
+
|
|
290
|
+
# --- extensions.json (merge recommendations) ---
|
|
291
|
+
extensions_path = vscode_dir / "extensions.json"
|
|
292
|
+
ext_defaults = json.loads((scaffold / "extensions.json").read_text())
|
|
293
|
+
recommended = ext_defaults["recommendations"]
|
|
294
|
+
if extensions_path.exists():
|
|
295
|
+
ext_data = json.loads(extensions_path.read_text())
|
|
296
|
+
existing_recs = ext_data.get("recommendations", [])
|
|
297
|
+
for ext_id in recommended:
|
|
298
|
+
if ext_id not in existing_recs:
|
|
299
|
+
existing_recs.append(ext_id)
|
|
300
|
+
ext_data["recommendations"] = existing_recs
|
|
301
|
+
extensions_path.write_text(json.dumps(ext_data, indent=4) + "\n")
|
|
302
|
+
print(f" Updated {_rel(extensions_path)}")
|
|
303
|
+
else:
|
|
304
|
+
extensions_path.write_text(json.dumps(ext_defaults, indent=4) + "\n")
|
|
305
|
+
print(f" Created {_rel(extensions_path)}")
|
|
306
|
+
|
|
307
|
+
# --- python.code-snippets ---
|
|
308
|
+
snippets_path = vscode_dir / "python.code-snippets"
|
|
309
|
+
snippets_path.write_text((scaffold / "python.code-snippets").read_text())
|
|
310
|
+
print(f" Created {_rel(snippets_path)}")
|
|
311
|
+
|
|
312
|
+
# --- templates/pyxflow_view.py ---
|
|
313
|
+
templates_dir = vscode_dir / "templates"
|
|
314
|
+
templates_dir.mkdir(exist_ok=True)
|
|
315
|
+
template_dest = templates_dir / "pyxflow_view.py"
|
|
316
|
+
template_dest.write_text((scaffold / "templates" / "pyxflow_view.py").read_text())
|
|
317
|
+
print(f" Created {_rel(template_dest)}")
|
|
318
|
+
|
|
319
|
+
# --- Install extensions ---
|
|
320
|
+
code_cmd = shutil.which("code")
|
|
321
|
+
if code_cmd:
|
|
322
|
+
for ext_id in recommended:
|
|
323
|
+
try:
|
|
324
|
+
subprocess.run(
|
|
325
|
+
[code_cmd, "--install-extension", ext_id],
|
|
326
|
+
capture_output=True, timeout=30,
|
|
327
|
+
)
|
|
328
|
+
print(f" Installed extension {ext_id}")
|
|
329
|
+
except (subprocess.TimeoutExpired, OSError):
|
|
330
|
+
print(f" Warning: failed to install {ext_id}")
|
|
331
|
+
else:
|
|
332
|
+
print(" Warning: 'code' CLI not found -- install extensions manually in VSCode")
|
|
333
|
+
|
|
334
|
+
print("\n VSCode configuration ready!")
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def _ensure_importable(views: str) -> None:
|
|
338
|
+
"""Make sure the views module is importable from the current directory."""
|
|
339
|
+
cwd = os.getcwd()
|
|
340
|
+
package = views.rsplit(".", 1)[0]
|
|
341
|
+
package_dir = os.path.join(cwd, package.replace(".", os.sep))
|
|
342
|
+
if os.path.isdir(package_dir):
|
|
343
|
+
# Package is a subdirectory of cwd (e.g. myapp/views/)
|
|
344
|
+
if cwd not in sys.path:
|
|
345
|
+
sys.path.insert(0, cwd)
|
|
346
|
+
elif os.path.isdir(os.path.join(cwd, "views")):
|
|
347
|
+
# Package is cwd itself (views/ at root, from --setup without name).
|
|
348
|
+
# Directory may have hyphens (app-1) while module uses underscores (app_1).
|
|
349
|
+
# Inject cwd as a synthetic package so `import app_1.views` works.
|
|
350
|
+
import types
|
|
351
|
+
pkg_mod = types.ModuleType(package)
|
|
352
|
+
pkg_mod.__path__ = [cwd]
|
|
353
|
+
pkg_mod.__package__ = package
|
|
354
|
+
sys.modules[package] = pkg_mod
|
|
355
|
+
# Also add cwd to sys.path so sibling packages (e.g. lib/) are importable.
|
|
356
|
+
if cwd not in sys.path:
|
|
357
|
+
sys.path.insert(0, cwd)
|
|
358
|
+
else:
|
|
359
|
+
if cwd not in sys.path:
|
|
360
|
+
sys.path.insert(0, cwd)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def main_deprecated():
|
|
364
|
+
"""Deprecated CLI entry point (``vaadin`` command)."""
|
|
365
|
+
print("WARNING: 'vaadin' command is deprecated. Use 'pyxflow' instead.", file=sys.stderr)
|
|
366
|
+
main()
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def main():
|
|
370
|
+
"""CLI entry point: ``pyxflow [app_module] [--dev] [--debug]``."""
|
|
371
|
+
if len(sys.argv) >= 2 and sys.argv[1] in ("-h", "--help"):
|
|
372
|
+
_usage()
|
|
373
|
+
|
|
374
|
+
# Parse all arguments: find module name (first non-flag) and flags.
|
|
375
|
+
# "bundle" is a subcommand alias for "--bundle"
|
|
376
|
+
_SUBCOMMANDS = {"bundle": "--bundle"}
|
|
377
|
+
# Flags that consume the next token as their value:
|
|
378
|
+
_VALUE_FLAGS = {"--vaadin-version", "--port", "--host"}
|
|
379
|
+
args = sys.argv[1:]
|
|
380
|
+
views = None
|
|
381
|
+
rest: list[str] = []
|
|
382
|
+
skip_next = False
|
|
383
|
+
for arg in args:
|
|
384
|
+
if skip_next:
|
|
385
|
+
rest.append(arg)
|
|
386
|
+
skip_next = False
|
|
387
|
+
elif arg in _VALUE_FLAGS:
|
|
388
|
+
rest.append(arg)
|
|
389
|
+
skip_next = True
|
|
390
|
+
elif arg in _SUBCOMMANDS:
|
|
391
|
+
rest.append(_SUBCOMMANDS[arg])
|
|
392
|
+
elif views is None and not arg.startswith("-"):
|
|
393
|
+
views = arg
|
|
394
|
+
else:
|
|
395
|
+
rest.append(arg)
|
|
396
|
+
|
|
397
|
+
if "--setup" in rest:
|
|
398
|
+
_setup_project(views)
|
|
399
|
+
_setup_vscode()
|
|
400
|
+
sys.exit(0)
|
|
401
|
+
|
|
402
|
+
if "--vscode" in rest:
|
|
403
|
+
_setup_vscode()
|
|
404
|
+
sys.exit(0)
|
|
405
|
+
|
|
406
|
+
if "--bundle" in rest:
|
|
407
|
+
from pathlib import Path
|
|
408
|
+
from pyxflow.bundle_generator import (
|
|
409
|
+
generate_and_build, copy_from_jars, _DEFAULT_VAADIN_VERSION,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
keep = "--keep" in rest
|
|
413
|
+
use_build = "--build" in rest
|
|
414
|
+
optimized = "--optimized" in rest
|
|
415
|
+
vaadin_version = _DEFAULT_VAADIN_VERSION
|
|
416
|
+
if "--vaadin-version" in rest:
|
|
417
|
+
idx = rest.index("--vaadin-version")
|
|
418
|
+
vaadin_version = rest[idx + 1]
|
|
419
|
+
|
|
420
|
+
# Resolve app_dir from module name if given
|
|
421
|
+
app_dir = None
|
|
422
|
+
if views:
|
|
423
|
+
# "demo" → "demo/", "my_app" → "my_app/"
|
|
424
|
+
app_dir = Path.cwd() / views.replace(".", os.sep).replace("-", "_")
|
|
425
|
+
|
|
426
|
+
cwd = os.getcwd()
|
|
427
|
+
if cwd not in sys.path:
|
|
428
|
+
sys.path.insert(0, cwd)
|
|
429
|
+
|
|
430
|
+
if use_build:
|
|
431
|
+
generate_and_build(app_dir=app_dir, keep=keep, vaadin_version=vaadin_version, optimized=optimized)
|
|
432
|
+
else:
|
|
433
|
+
# Default: copy from Maven JARs (fast, no build needed)
|
|
434
|
+
is_pyxflow_dev = (Path.cwd() / "src" / "pyxflow").is_dir()
|
|
435
|
+
if is_pyxflow_dev:
|
|
436
|
+
bundle_dir = Path.cwd() / "src" / "pyxflow" / "bundle"
|
|
437
|
+
elif app_dir:
|
|
438
|
+
bundle_dir = app_dir / "bundle"
|
|
439
|
+
else:
|
|
440
|
+
print("ERROR: Cannot determine bundle output directory.")
|
|
441
|
+
print(" Run from a pyxflow source tree (src/pyxflow/ exists)")
|
|
442
|
+
print(" or specify an app module: pyxflow <app_module> bundle")
|
|
443
|
+
sys.exit(1)
|
|
444
|
+
|
|
445
|
+
print("===================================================")
|
|
446
|
+
print(" Vaadin PyXFlow Bundle Generator (copy mode)")
|
|
447
|
+
print("===================================================")
|
|
448
|
+
print(f" Vaadin version: {vaadin_version}")
|
|
449
|
+
print(f" Bundle output: {bundle_dir}")
|
|
450
|
+
print()
|
|
451
|
+
|
|
452
|
+
copy_from_jars(bundle_dir, vaadin_version, optimized=optimized)
|
|
453
|
+
|
|
454
|
+
print()
|
|
455
|
+
print("===================================================")
|
|
456
|
+
print(" Bundle copied successfully!")
|
|
457
|
+
print("===================================================")
|
|
458
|
+
sys.exit(0)
|
|
459
|
+
|
|
460
|
+
if views is None or views == ".":
|
|
461
|
+
views = _auto_detect_app()
|
|
462
|
+
if views is None:
|
|
463
|
+
print(" No views/ directory found in the current directory.")
|
|
464
|
+
print()
|
|
465
|
+
print(" To scaffold a new project: vaadin --setup")
|
|
466
|
+
print(" Or create views/ manually: mkdir -p views && touch views/__init__.py")
|
|
467
|
+
print()
|
|
468
|
+
_usage()
|
|
469
|
+
|
|
470
|
+
if "." not in views:
|
|
471
|
+
views = f"{views}.views"
|
|
472
|
+
|
|
473
|
+
_ensure_importable(views)
|
|
474
|
+
|
|
475
|
+
port = 8080
|
|
476
|
+
host = "localhost"
|
|
477
|
+
if "--port" in rest:
|
|
478
|
+
idx = rest.index("--port")
|
|
479
|
+
port = int(rest[idx + 1])
|
|
480
|
+
rest = rest[:idx] + rest[idx + 2:]
|
|
481
|
+
if "--host" in rest:
|
|
482
|
+
idx = rest.index("--host")
|
|
483
|
+
host = rest[idx + 1]
|
|
484
|
+
rest = rest[:idx] + rest[idx + 2:]
|
|
485
|
+
|
|
486
|
+
debug = "--debug" in rest
|
|
487
|
+
dev = "--dev" in rest
|
|
488
|
+
|
|
489
|
+
if dev:
|
|
490
|
+
# Reuse FlowApp dev mode
|
|
491
|
+
app = FlowApp.__new__(FlowApp)
|
|
492
|
+
app._views = views
|
|
493
|
+
app._port = port
|
|
494
|
+
app._host = host
|
|
495
|
+
app._run_dev(debug)
|
|
496
|
+
else:
|
|
497
|
+
_serve(views, host, port, debug, dev=dev)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _dev_serve():
|
|
501
|
+
"""Entry point for dev-mode child process (reads config from env)."""
|
|
502
|
+
try:
|
|
503
|
+
cfg = json.loads(os.environ["_PYFLOW_APP"])
|
|
504
|
+
_ensure_importable(cfg["views"])
|
|
505
|
+
_serve(cfg["views"], cfg["host"], cfg["port"], cfg["debug"],
|
|
506
|
+
dev=True, socket_fd=cfg.get("socket_fd"))
|
|
507
|
+
except KeyboardInterrupt:
|
|
508
|
+
pass
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def _serve(views: str, host: str, port: int, debug: bool, *, dev: bool = False, socket_fd: int | None = None):
|
|
512
|
+
import importlib
|
|
513
|
+
from pathlib import Path
|
|
514
|
+
from pyxflow.router import discover_views
|
|
515
|
+
from pyxflow.server.http_server import run_server, set_app_directory
|
|
516
|
+
import pyxflow.server.http_server as _http
|
|
517
|
+
|
|
518
|
+
_http._dev_mode = dev
|
|
519
|
+
_http._views_module = views
|
|
520
|
+
discover_views(views)
|
|
521
|
+
|
|
522
|
+
# Resolve app package directory (e.g. "demo.views" → demo/)
|
|
523
|
+
package = views.rsplit(".", 1)[0]
|
|
524
|
+
pkg_mod = importlib.import_module(package)
|
|
525
|
+
if getattr(pkg_mod, "__file__", None):
|
|
526
|
+
set_app_directory(Path(pkg_mod.__file__).parent)
|
|
527
|
+
elif hasattr(pkg_mod, "__path__"):
|
|
528
|
+
# Namespace or synthetic package — use __path__
|
|
529
|
+
set_app_directory(Path(list(pkg_mod.__path__)[0]))
|
|
530
|
+
|
|
531
|
+
if socket_fd is not None:
|
|
532
|
+
import socket
|
|
533
|
+
sock = socket.socket(fileno=socket_fd)
|
|
534
|
+
run_server(debug=debug, sock=sock)
|
|
535
|
+
else:
|
|
536
|
+
run_server(host=host, port=port, debug=debug)
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const h=function(l){window.Vaadin=window.Vaadin||{},window.Vaadin.Flow=window.Vaadin.Flow||{};var r={},a={},t;typeof window.console===void 0||!window.location.search.match(/[&?]debug(&|$)/)?t=function(){}:typeof window.console.log=="function"?t=function(){window.console.log.apply(window.console,arguments)}:t=window.console.log;var f=function(n){var o=document.getElementById(n);if(!o)return!1;for(var i=0;i<o.childElementCount;i++){var e=o.childNodes[i].className;if(e&&e.indexOf("v-app-loading")!=-1)return!1}return!0};window.Vaadin=window.Vaadin||{},window.Vaadin.Flow=window.Vaadin.Flow||{},window.Vaadin.Flow.tryCatchWrapper=function(n,o){return function(){try{return n.apply(this,arguments)}catch(i){console.error(`There seems to be an error in ${o}:
|
|
2
|
+
${i.message}
|
|
3
|
+
Please submit an issue to https://github.com/vaadin/flow-components/issues/new/choose`)}}},window.Vaadin.Flow.initApplication||(window.Vaadin.Flow.clients=window.Vaadin.Flow.clients||{},window.Vaadin.Flow.initApplication=function(n,o){var i=n.replace(/-\d+$/,"");if(r[n]){if(window.Vaadin&&window.Vaadin.Flow&&window.Vaadin.Flow.clients&&window.Vaadin.Flow.clients[i]&&window.Vaadin.Flow.clients[i].initializing)throw new Error("Application "+n+" is already being initialized");if(f(n)){if(l.appConfig.productionMode)throw new Error("Application "+n+" already initialized");for(var e=document.getElementById(n),w=0;w<e.childElementCount;w++)e.childNodes[w].remove();const s={getConfig:function(V){return o[V]}};return r[n]=s,a.client.callback?(t("Starting from bootstrap",n),a.client.callback(n)):(t("Setting pending startup",n),a.client.pendingApps.push(n)),r[n]}}t("init application",n,o),window.Vaadin.Flow.clients[i]={isActive:function(){return!0},initializing:!0,productionMode:p};var v=function(g){var s=o[g];return s},u={getConfig:v};r[n]=u;var d="client";return a[d]={pendingApps:[]},a[d].callback?(t("Starting from bootstrap",n),a[d].callback(n)):(t("Setting pending startup",n),a[d].pendingApps.push(n)),u},window.Vaadin.Flow.getAppIds=function(){var n=[];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&n.push(o);return n},window.Vaadin.Flow.getApp=function(n){return r[n]},window.Vaadin.Flow.registerWidgetset=function(n,o){t("Widgetset registered",n);var i=a[n];if(i&&i.pendingApps){i.callback=o;for(var e=0;e<i.pendingApps.length;e++){var w=i.pendingApps[e];t("Starting from register widgetset",w),o(w)}i.pendingApps=null}}),t("Flow bootstrap loaded"),l.appConfig.productionMode&&typeof window.__gwtStatsEvent!="function"&&(window.Vaadin.Flow.gwtStatsEvents=[],window.__gwtStatsEvent=function(n){return window.Vaadin.Flow.gwtStatsEvents.push(n),!0});var c=l.appConfig,p=l.appConfig.productionMode;window.Vaadin.Flow.initApplication(c.appId,c)};export{h as init};
|
|
Binary file
|