jac-client 0.2.11__tar.gz → 0.2.13__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.
- {jac_client-0.2.11 → jac_client-0.2.13}/PKG-INFO +2 -2
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/cli.jac +3 -3
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/client_runtime.cl.jac +3 -2
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/impl/client_runtime.impl.jac +17 -6
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/compiler.jac +4 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/config_loader.jac +1 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/compiler.impl.jac +16 -39
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/config_loader.impl.jac +8 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/vite_bundler.impl.jac +74 -23
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/desktop/sidecar/main.py +42 -23
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/desktop_target.jac +4 -2
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/impl/desktop_target.impl.jac +324 -112
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/vite_bundler.jac +18 -3
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/utils/__init__.jac +1 -0
- jac_client-0.2.13/jac_client/plugin/utils/client_deps.jac +14 -0
- jac_client-0.2.13/jac_client/plugin/utils/impl/client_deps.impl.jac +73 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/templates/client.jacpack +0 -4
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/templates/fullstack.jacpack +0 -4
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/test_cli.py +142 -0
- jac_client-0.2.13/jac_client/tests/test_desktop_api_url.py +854 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/test_e2e.py +12 -12
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/test_it.py +209 -11
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/PKG-INFO +2 -2
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/SOURCES.txt +3 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/requires.txt +1 -1
- {jac_client-0.2.11 → jac_client-0.2.13}/pyproject.toml +2 -2
- {jac_client-0.2.11 → jac_client-0.2.13}/README.md +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/assets/workers/worker.py +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/CategoryFilter.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/Header.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/ProfitOverview.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/Summary.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/TransactionForm.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/TransactionItem.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/TransactionList.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/components/navigation.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/constants/categories.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/constants/clients.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/context/BudgetContext.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/hooks/useBudget.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/hooks/useLocalStorage.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/BudgetPlanner.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/FeaturesTest.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/LandingPage.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/loginPage.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/nestedDemo.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/notFound.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/pages/signupPage.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/all-in-one/utils/formatters.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/asset-serving/css-with-image/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/asset-serving/image-asset/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/asset-serving/import-alias/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/basic/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/basic-auth/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/basic-auth-with-router/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/basic-full-stack/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/js-styling/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/material-ui/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/pure-css/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/sass-example/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/styled-components/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/css-styling/tailwind-example/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/full-stack-with-auth/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/little-x/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/little-x/src/submit-button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-advance/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-basic/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-basic/src/button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/nested-folders/nested-basic/src/components/button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/ts-support/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/examples/with-router/main.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/client.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/impl/client.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/impl/vite_client_bundle.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/plugin_config.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/__init__.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/asset_processor.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/desktop_config.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/asset_processor.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/desktop_config.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/import_processor.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/jac_to_js.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/impl/package_installer.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/import_processor.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/jac_to_js.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/package_installer.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/impl/registry.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/impl/web_target.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/register.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/registry.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/web_target.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/utils/bun_installer.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/utils/impl/bun_installer.impl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/vite_client_bundle.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/__init__.py +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/conftest.py +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/basic-app/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/cl_file/app.cl.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/cl_file/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/js_import/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/relative_import/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/relative_import/button.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/spawn_test/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/fixtures/with-ts/app.jac +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/test_helpers.py +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client/tests/test_it_desktop.py +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/dependency_links.txt +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/entry_points.txt +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/jac_client.egg-info/top_level.txt +0 -0
- {jac_client-0.2.11 → jac_client-0.2.13}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jac-client
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.13
|
|
4
4
|
Summary: Build full-stack web applications with Jac - one language for frontend and backend.
|
|
5
5
|
Author-email: Jason Mars <jason@mars.ninja>
|
|
6
6
|
Maintainer-email: Jason Mars <jason@mars.ninja>
|
|
@@ -11,7 +11,7 @@ Project-URL: Documentation, https://jac-lang.org
|
|
|
11
11
|
Keywords: jac,jaclang,jaseci,frontend,full-stack,web-development
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
|
-
Requires-Dist: jaclang>=0.9.
|
|
14
|
+
Requires-Dist: jaclang>=0.9.13
|
|
15
15
|
Provides-Extra: dev
|
|
16
16
|
Requires-Dist: python-dotenv==1.0.1; extra == "dev"
|
|
17
17
|
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
@@ -426,15 +426,15 @@ def _handle_start_target(ctx: HookContext) -> None {
|
|
|
426
426
|
ctx.set_data("cancel_return_code", 1);
|
|
427
427
|
return;
|
|
428
428
|
}
|
|
429
|
-
# Check if --dev flag is set
|
|
430
429
|
dev_mode = ctx.get_arg("dev", False);
|
|
430
|
+
api_port = ctx.get_arg("port", 8000);
|
|
431
431
|
try {
|
|
432
432
|
if dev_mode {
|
|
433
433
|
# Desktop target with --dev: launch Tauri dev mode (hot reload)
|
|
434
|
-
target.dev(entry_path, project_dir);
|
|
434
|
+
target.dev(entry_path, project_dir, api_port=api_port);
|
|
435
435
|
} else {
|
|
436
436
|
# Desktop target without --dev: build web bundle and launch Tauri with built bundle
|
|
437
|
-
target.start(entry_path, project_dir);
|
|
437
|
+
target.start(entry_path, project_dir, api_port=api_port);
|
|
438
438
|
}
|
|
439
439
|
ctx.set_data("cancel_execution", True);
|
|
440
440
|
ctx.set_data("cancel_return_code", 0);
|
|
@@ -4,7 +4,7 @@ import from 'react' { * as React }
|
|
|
4
4
|
import from 'react' { useState as reactUseState, useEffect as reactUseEffect }
|
|
5
5
|
import from 'react-dom/client' { * as ReactDOM }
|
|
6
6
|
import from 'react-router-dom' {
|
|
7
|
-
|
|
7
|
+
BrowserRouter as ReactRouterBrowserRouter,
|
|
8
8
|
Routes as ReactRouterRoutes,
|
|
9
9
|
Route as ReactRouterRoute,
|
|
10
10
|
Link as ReactRouterLink,
|
|
@@ -21,7 +21,7 @@ def:pub __jacJsx(tag: any, props: dict = {}, children: any = []) -> any;
|
|
|
21
21
|
glob:
|
|
22
22
|
pub useState = reactUseState,
|
|
23
23
|
useEffect = reactUseEffect,
|
|
24
|
-
Router =
|
|
24
|
+
Router = ReactRouterBrowserRouter,
|
|
25
25
|
Routes = ReactRouterRoutes,
|
|
26
26
|
Route = ReactRouterRoute,
|
|
27
27
|
Link = ReactRouterLink,
|
|
@@ -40,6 +40,7 @@ async def:pub jacSignup(username: str, password: str) -> dict;
|
|
|
40
40
|
async def:pub jacLogin(username: str, password: str) -> bool;
|
|
41
41
|
def:pub jacLogout -> None;
|
|
42
42
|
def:pub jacIsLoggedIn -> bool;
|
|
43
|
+
def:pub __getApiBaseUrl -> str;
|
|
43
44
|
def:pub __getLocalStorage(key: str) -> str;
|
|
44
45
|
def:pub __setLocalStorage(key: str, value: str) -> None;
|
|
45
46
|
def:pub __removeLocalStorage(key: str) -> None;
|
|
@@ -42,14 +42,22 @@ impl useRouter -> dict {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
impl navigate(path: str) -> None {
|
|
45
|
-
window.
|
|
45
|
+
window.history.pushState({}, "", path);
|
|
46
|
+
window.dispatchEvent(Reflect.construct(PopStateEvent, ["popstate"]));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
impl __getApiBaseUrl -> str {
|
|
50
|
+
# globalThis.__JAC_API_BASE_URL__ is replaced by Vite's define at build time.
|
|
51
|
+
# Falls back to empty string (same-origin) when not configured.
|
|
52
|
+
return globalThis.__JAC_API_BASE_URL__ || "";
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
impl __jacSpawn(left: str, right: str = "", fields: dict = {}) -> any {
|
|
49
56
|
token = __getLocalStorage("jac_token");
|
|
50
|
-
|
|
57
|
+
base_url = __getApiBaseUrl();
|
|
58
|
+
url = f"{base_url}/walker/{left}";
|
|
51
59
|
if right != "" {
|
|
52
|
-
url = f"/walker/{left}/{right}";
|
|
60
|
+
url = f"{base_url}/walker/{left}/{right}";
|
|
53
61
|
}
|
|
54
62
|
response = await fetch(
|
|
55
63
|
url,
|
|
@@ -78,8 +86,9 @@ impl jacSpawn(left: str, right: str = "", fields: dict = {}) -> any {
|
|
|
78
86
|
|
|
79
87
|
impl __jacCallFunction(function_name: str, args: dict = {}) -> any {
|
|
80
88
|
token = __getLocalStorage("jac_token");
|
|
89
|
+
base_url = __getApiBaseUrl();
|
|
81
90
|
response = await fetch(
|
|
82
|
-
f"/function/{function_name}",
|
|
91
|
+
f"{base_url}/function/{function_name}",
|
|
83
92
|
{
|
|
84
93
|
"method": "POST",
|
|
85
94
|
"headers": {
|
|
@@ -104,8 +113,9 @@ impl __jacCallFunction(function_name: str, args: dict = {}) -> any {
|
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
impl jacSignup(username: str, password: str) -> dict {
|
|
116
|
+
base_url = __getApiBaseUrl();
|
|
107
117
|
response = await fetch(
|
|
108
|
-
"/user/register",
|
|
118
|
+
f"{base_url}/user/register",
|
|
109
119
|
{
|
|
110
120
|
"method": "POST",
|
|
111
121
|
"headers": {"Content-Type": "application/json"},
|
|
@@ -140,8 +150,9 @@ impl jacSignup(username: str, password: str) -> dict {
|
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
impl jacLogin(username: str, password: str) -> bool {
|
|
153
|
+
base_url = __getApiBaseUrl();
|
|
143
154
|
response = await fetch(
|
|
144
|
-
"/user/login",
|
|
155
|
+
f"{base_url}/user/login",
|
|
145
156
|
{
|
|
146
157
|
"method": "POST",
|
|
147
158
|
"headers": {"Content-Type": "application/json"},
|
|
@@ -63,4 +63,8 @@ class ViteCompiler {
|
|
|
63
63
|
def compile_and_bundle(
|
|
64
64
|
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
65
65
|
) -> tuple[str, str, list[str], list[str]];
|
|
66
|
+
|
|
67
|
+
def compile(
|
|
68
|
+
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
69
|
+
) -> tuple[list[str], list[str]];
|
|
66
70
|
}
|
|
@@ -19,6 +19,7 @@ class JacClientConfig(PluginConfigBase) {
|
|
|
19
19
|
override def get_default_config(self: JacClientConfig) -> dict[str, Any];
|
|
20
20
|
override def load(self: JacClientConfig) -> dict[str, Any];
|
|
21
21
|
def save(self: JacClientConfig) -> None;
|
|
22
|
+
def get_api_config(self: JacClientConfig) -> dict[str, Any];
|
|
22
23
|
def get_vite_config(self: JacClientConfig) -> dict[str, Any];
|
|
23
24
|
def get_ts_config(self: JacClientConfig) -> dict[str, Any];
|
|
24
25
|
def get_configs(self: JacClientConfig) -> dict[str, Any];
|
|
@@ -12,10 +12,10 @@ impl ViteCompiler._get_client_dir(self: ViteCompiler) -> Path {
|
|
|
12
12
|
return self.project_dir / '.jac' / 'client';
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
"""Compile module and dependencies
|
|
16
|
-
impl ViteCompiler.
|
|
15
|
+
"""Compile module and dependencies without bundling (for dev mode)."""
|
|
16
|
+
impl ViteCompiler.compile(
|
|
17
17
|
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
18
|
-
) -> tuple[
|
|
18
|
+
) -> tuple[list[str], list[str]] {
|
|
19
19
|
(module_js, mod, module_manifest) = self.jac_compiler.compile_module(module_path);
|
|
20
20
|
collected_exports: set[str] = set(
|
|
21
21
|
self.jac_compiler.extract_exports(module_manifest)
|
|
@@ -32,13 +32,22 @@ impl ViteCompiler.compile_and_bundle(
|
|
|
32
32
|
self.compile_runtime_utils();
|
|
33
33
|
self.copy_root_assets();
|
|
34
34
|
self.create_entry_file(module_path);
|
|
35
|
+
# Return exports and globals without bundling
|
|
36
|
+
client_exports = sorted(collected_exports);
|
|
37
|
+
client_globals = list(collected_globals.keys());
|
|
38
|
+
return (client_exports, client_globals);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
"""Compile module and dependencies, then bundle with Vite."""
|
|
42
|
+
impl ViteCompiler.compile_and_bundle(
|
|
43
|
+
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
44
|
+
) -> tuple[str, str, list[str], list[str]] {
|
|
45
|
+
(client_exports, client_globals) = self.compile(module, module_path);
|
|
35
46
|
# Vite handles JSX/TSX transpilation natively with Bun - no Babel needed
|
|
36
47
|
# Vite builds directly from compiled/ directory
|
|
37
48
|
entry_file = self.compiled_dir / '_entry.js';
|
|
38
49
|
self.vite_bundler.build(entry_file=entry_file);
|
|
39
50
|
(bundle_code, bundle_hash) = self.vite_bundler.read_bundle();
|
|
40
|
-
client_exports = sorted(collected_exports);
|
|
41
|
-
client_globals = list(collected_globals.keys());
|
|
42
51
|
return (bundle_code, bundle_hash, client_exports, client_globals);
|
|
43
52
|
}
|
|
44
53
|
|
|
@@ -187,20 +196,7 @@ impl ViteCompiler.compile_dependencies_recursively(
|
|
|
187
196
|
output_path = self.compiled_dir / name;
|
|
188
197
|
}
|
|
189
198
|
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
190
|
-
# Add source file header comment for better error messages
|
|
191
199
|
source_header = f"/* Source: {module_path} */\n";
|
|
192
|
-
# Add ES module exports so Vite can resolve named imports between modules
|
|
193
|
-
module_export_names = sorted(set(exports_list + list(non_root_globals.keys())));
|
|
194
|
-
if module_export_names {
|
|
195
|
-
import re;
|
|
196
|
-
# Strip any existing export declarations to avoid duplicates
|
|
197
|
-
clean_combined_js = re.sub(r'\nexport\s*\{[^}]*\}\s*;?\s*', '\n', combined_js);
|
|
198
|
-
clean_combined_js = re.sub(
|
|
199
|
-
r'\bexport\s+(let|const|var|function|class)\b', r'\1', clean_combined_js
|
|
200
|
-
);
|
|
201
|
-
export_stmt = f"\nexport {{ {', '.join(module_export_names)} }};\n";
|
|
202
|
-
combined_js = clean_combined_js + export_stmt;
|
|
203
|
-
}
|
|
204
200
|
output_path.write_text(source_header + combined_js, encoding='utf-8');
|
|
205
201
|
if (not manifest or not manifest.imports) {
|
|
206
202
|
return;
|
|
@@ -240,34 +236,15 @@ impl ViteCompiler.compile_runtime_utils(self: ViteCompiler) -> tuple[str, list[s
|
|
|
240
236
|
runtimeutils_exports_list = self.jac_compiler.extract_exports(
|
|
241
237
|
runtimeutils_manifest
|
|
242
238
|
);
|
|
243
|
-
# Include both function exports and glob exports (e.g., useState, useEffect)
|
|
244
239
|
glob_names = list(runtimeutils_manifest.globals) if runtimeutils_manifest else [];
|
|
245
240
|
all_exports = sorted(
|
|
246
241
|
set(runtimeutils_exports_list + self.ROUTER_EXPORTS + glob_names)
|
|
247
242
|
);
|
|
248
|
-
# Strip all existing export statements from compiled JS to avoid duplicates.
|
|
249
|
-
# The codegen produces `export let`, `export function`, `export class`, and
|
|
250
|
-
# `export { ... }` forms. We remove the export keyword from declarations and
|
|
251
|
-
# remove export blocks entirely, then add one comprehensive export at the end.
|
|
252
|
-
import re;
|
|
253
|
-
clean_js = re.sub(r'\nexport\s*\{[^}]*\}\s*;?\s*', '\n', runtimeutils_js);
|
|
254
|
-
clean_js = re.sub(r'\bexport\s+(let|const|var|function|class)\b', r'\1', clean_js);
|
|
255
|
-
# Append single comprehensive ES module export for Vite to resolve @jac/runtime
|
|
256
|
-
export_names = [
|
|
257
|
-
e
|
|
258
|
-
for e in all_exports
|
|
259
|
-
if not e.startswith('_')
|
|
260
|
-
];
|
|
261
|
-
# Also include internal names that are imported by compiled modules
|
|
262
|
-
internal_exports = ['__jacJsx', '__jacSpawn', '__jacCallFunction'];
|
|
263
|
-
all_export_names = sorted(set(export_names + internal_exports));
|
|
264
|
-
export_stmt = f"\nexport {{ {', '.join(all_export_names)} }};\n";
|
|
265
|
-
combined_runtime_utils_js = clean_js + export_stmt;
|
|
266
243
|
self.compiled_dir.mkdir(parents=True, exist_ok=True);
|
|
267
244
|
(self.compiled_dir / 'client_runtime.js').write_text(
|
|
268
|
-
|
|
245
|
+
runtimeutils_js, encoding='utf-8'
|
|
269
246
|
);
|
|
270
|
-
return (
|
|
247
|
+
return (runtimeutils_js, all_exports);
|
|
271
248
|
}
|
|
272
249
|
|
|
273
250
|
"""Initialize the Vite compiler."""
|
|
@@ -19,6 +19,7 @@ impl JacClientConfig.get_plugin_name(self: JacClientConfig) -> str {
|
|
|
19
19
|
"""Get default configuration structure for client."""
|
|
20
20
|
impl JacClientConfig.get_default_config(self: JacClientConfig) -> dict[str, Any] {
|
|
21
21
|
return {
|
|
22
|
+
'api': {'base_url': ''},
|
|
22
23
|
'vite': {
|
|
23
24
|
'plugins': [],
|
|
24
25
|
'lib_imports': [],
|
|
@@ -60,6 +61,7 @@ impl JacClientConfig.load(self: JacClientConfig) -> dict[str, Any] {
|
|
|
60
61
|
else {};
|
|
61
62
|
# Build user config in the expected internal format
|
|
62
63
|
user_config: dict[str, Any] = {
|
|
64
|
+
'api': client_config.get('api', {}),
|
|
63
65
|
'vite': client_config.get('vite', {}),
|
|
64
66
|
'ts': client_config.get('ts', {}),
|
|
65
67
|
'configs': client_config.get('configs', {}),
|
|
@@ -81,6 +83,12 @@ impl JacClientConfig.get_package_config(self: JacClientConfig) -> dict[str, Any]
|
|
|
81
83
|
return config.get('package', {});
|
|
82
84
|
}
|
|
83
85
|
|
|
86
|
+
"""Get API configuration (base_url for backend)."""
|
|
87
|
+
impl JacClientConfig.get_api_config(self: JacClientConfig) -> dict[str, Any] {
|
|
88
|
+
config = self.load();
|
|
89
|
+
return config.get('api', {});
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
"""Get Vite-specific configuration."""
|
|
85
93
|
impl JacClientConfig.get_vite_config(self: JacClientConfig) -> dict[str, Any] {
|
|
86
94
|
config = self.load();
|
|
@@ -216,6 +216,19 @@ impl ViteBundler._format_plugin_options(self: ViteBundler, options: dict) -> str
|
|
|
216
216
|
return '{ ' + ', '.join(items) + ' }';
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
"""Resolve the API base URL using a consistent priority chain.
|
|
220
|
+
|
|
221
|
+
Priority: jac.toml base_url > direct override > env var (desktop start) > "" (same-origin)
|
|
222
|
+
"""
|
|
223
|
+
impl ViteBundler._resolve_api_base_url(
|
|
224
|
+
self: ViteBundler, api_base_url_override: str = ""
|
|
225
|
+
) -> str {
|
|
226
|
+
api_config_data = self.config_loader.get_api_config();
|
|
227
|
+
toml_base_url = api_config_data.get('base_url', '');
|
|
228
|
+
env_override = os.environ.get(API_BASE_URL_ENV_VAR, '');
|
|
229
|
+
return toml_base_url or api_base_url_override or env_override;
|
|
230
|
+
}
|
|
231
|
+
|
|
219
232
|
"""Get a valid JavaScript variable name from plugin module name."""
|
|
220
233
|
impl ViteBundler._get_plugin_var_name(self: ViteBundler, plugin_name: str) -> str {
|
|
221
234
|
name = plugin_name.split('/')[-1];
|
|
@@ -224,13 +237,20 @@ impl ViteBundler._get_plugin_var_name(self: ViteBundler, plugin_name: str) -> st
|
|
|
224
237
|
return name;
|
|
225
238
|
}
|
|
226
239
|
|
|
227
|
-
"""Create vite.config.js from config.json during bundling.
|
|
228
|
-
|
|
240
|
+
"""Create vite.config.js from config.json during bundling.
|
|
241
|
+
|
|
242
|
+
api_base_url_override: overrides jac.toml base_url for desktop targets
|
|
243
|
+
where the CLI knows the backend port at startup time.
|
|
244
|
+
"""
|
|
245
|
+
impl ViteBundler.create_vite_config(
|
|
246
|
+
self: ViteBundler, entry_file: Path, api_base_url_override: str = ""
|
|
247
|
+
) -> Path {
|
|
229
248
|
build_dir = self._get_client_dir();
|
|
230
249
|
build_dir.mkdir(parents=True, exist_ok=True);
|
|
231
250
|
configs_dir = build_dir / 'configs';
|
|
232
251
|
configs_dir.mkdir(exist_ok=True);
|
|
233
252
|
vite_config_data = self.config_loader.get_vite_config();
|
|
253
|
+
api_base_url = self._resolve_api_base_url(api_base_url_override);
|
|
234
254
|
config_path = configs_dir / 'vite.config.js';
|
|
235
255
|
# TypeScript is always enabled by default
|
|
236
256
|
try {
|
|
@@ -355,6 +375,9 @@ function jacSourceMapper() {{
|
|
|
355
375
|
*/
|
|
356
376
|
|
|
357
377
|
export default defineConfig({{
|
|
378
|
+
define: {{
|
|
379
|
+
'globalThis.__JAC_API_BASE_URL__': '"{api_base_url}"',
|
|
380
|
+
}},
|
|
358
381
|
plugins: [
|
|
359
382
|
jacSourceMapper(),{(newline + plugins_str + newline + ' ') if plugins_str else ''}],
|
|
360
383
|
root: buildDir, // base folder (.jac/client/) so vite can find node_modules
|
|
@@ -426,22 +449,29 @@ impl ViteBundler.build(self: ViteBundler, entry_file: Optional[Path] = None) ->
|
|
|
426
449
|
import sys;
|
|
427
450
|
import time;
|
|
428
451
|
import shutil;
|
|
429
|
-
import from jac_client.plugin.utils { ensure_bun_available }
|
|
452
|
+
import from jac_client.plugin.utils { ensure_bun_available, ensure_client_deps }
|
|
430
453
|
# Ensure bun is available before proceeding
|
|
431
454
|
if not ensure_bun_available() {
|
|
432
455
|
raise ClientBundleError('Bun is required. Install manually: https://bun.sh') from None ;
|
|
433
456
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
self.create_tsconfig();
|
|
457
|
+
# Ensure client npm deps are configured; prompt to install defaults if missing
|
|
458
|
+
if not ensure_client_deps(self.config_loader) {
|
|
459
|
+
raise ClientBundleError(
|
|
460
|
+
'Client dependencies not configured. Add [dependencies.npm] to jac.toml '
|
|
461
|
+
'or create a project with: jac create --use client'
|
|
462
|
+
) from None ;
|
|
441
463
|
}
|
|
464
|
+
self.output_dir.mkdir(parents=True, exist_ok=True);
|
|
465
|
+
# Always regenerate package.json to pick up any dependency changes
|
|
466
|
+
self.create_package_json();
|
|
442
467
|
try {
|
|
443
468
|
build_dir = self._get_client_dir();
|
|
444
469
|
node_modules = build_dir / 'node_modules';
|
|
470
|
+
# Reinstall if node_modules is missing or stale (e.g. empty from a prior failed install)
|
|
471
|
+
vite_bin = node_modules / '.bin' / 'vite';
|
|
472
|
+
if node_modules.exists() and not vite_bin.exists() {
|
|
473
|
+
shutil.rmtree(node_modules);
|
|
474
|
+
}
|
|
445
475
|
if not node_modules.exists() {
|
|
446
476
|
# Temporarily copy package.json to client build dir for bun install
|
|
447
477
|
build_package_json = build_dir / 'package.json';
|
|
@@ -455,15 +485,17 @@ impl ViteBundler.build(self: ViteBundler, entry_file: Optional[Path] = None) ->
|
|
|
455
485
|
print("\n ⏳ Installing dependencies...\n", flush=True);
|
|
456
486
|
start_time = time.time();
|
|
457
487
|
result = subprocess.run(
|
|
458
|
-
['bun', 'install'],
|
|
488
|
+
['bun', 'install'],
|
|
489
|
+
cwd=build_dir,
|
|
490
|
+
check=False,
|
|
491
|
+
text=True,
|
|
492
|
+
capture_output=True
|
|
459
493
|
);
|
|
460
494
|
elapsed = time.time() - start_time;
|
|
461
495
|
if result.returncode != 0 {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
);
|
|
466
|
-
raise ClientBundleError("Failed to install dependencies") ;
|
|
496
|
+
error_output = result.stderr or result.stdout;
|
|
497
|
+
error_msg = f"Dependency installation failed after {elapsed:.1f}s\n\n{error_output}\nCommand: bun install";
|
|
498
|
+
raise ClientBundleError(error_msg) from None ;
|
|
467
499
|
}
|
|
468
500
|
print(f"\n ✔ Dependencies installed ({elapsed:.1f}s)", flush=True);
|
|
469
501
|
} except FileNotFoundError {
|
|
@@ -500,13 +532,16 @@ impl ViteBundler.build(self: ViteBundler, entry_file: Optional[Path] = None) ->
|
|
|
500
532
|
# Run vite from client build directory so it can find node_modules
|
|
501
533
|
print("\n ⏳ Building client bundle...\n", flush=True);
|
|
502
534
|
start_time = time.time();
|
|
503
|
-
result = subprocess.run(
|
|
535
|
+
result = subprocess.run(
|
|
536
|
+
command, cwd=build_dir, check=False, text=True, capture_output=True
|
|
537
|
+
);
|
|
504
538
|
elapsed = time.time() - start_time;
|
|
505
539
|
if result.returncode != 0 {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
)
|
|
540
|
+
error_output = result.stderr or result.stdout;
|
|
541
|
+
error_msg = f"Vite build failed after {elapsed:.1f}s\n\n{error_output}\nCommand: {' '.join(
|
|
542
|
+
command
|
|
543
|
+
)}";
|
|
544
|
+
raise ClientBundleError(error_msg) from None ;
|
|
510
545
|
}
|
|
511
546
|
print(f"\n ✔ Client bundle built ({elapsed:.1f}s)", flush=True);
|
|
512
547
|
} finally {
|
|
@@ -543,15 +578,23 @@ impl ViteBundler.init(
|
|
|
543
578
|
self.output_dir = output_dir or (self._get_client_dir() / 'dist');
|
|
544
579
|
}
|
|
545
580
|
|
|
546
|
-
"""Create a dev-mode vite config with API proxy for HMR.
|
|
581
|
+
"""Create a dev-mode vite config with API proxy for HMR.
|
|
582
|
+
|
|
583
|
+
api_base_url_override: when set, API calls go directly to this URL
|
|
584
|
+
instead of via proxy (used by desktop targets).
|
|
585
|
+
"""
|
|
547
586
|
impl ViteBundler.create_dev_vite_config(
|
|
548
|
-
self: ViteBundler,
|
|
587
|
+
self: ViteBundler,
|
|
588
|
+
entry_file: Path,
|
|
589
|
+
api_port: int = 8000,
|
|
590
|
+
api_base_url_override: str = ""
|
|
549
591
|
) -> Path {
|
|
550
592
|
build_dir = self._get_client_dir();
|
|
551
593
|
build_dir.mkdir(parents=True, exist_ok=True);
|
|
552
594
|
configs_dir = build_dir / 'configs';
|
|
553
595
|
configs_dir.mkdir(exist_ok=True);
|
|
554
596
|
config_path = configs_dir / 'vite.dev.config.js';
|
|
597
|
+
api_base_url = self._resolve_api_base_url(api_base_url_override);
|
|
555
598
|
# Get entry file relative path
|
|
556
599
|
try {
|
|
557
600
|
entry_relative = entry_file.relative_to(build_dir).as_posix();
|
|
@@ -587,9 +630,13 @@ const projectRoot = path.resolve(__dirname, "../../..");
|
|
|
587
630
|
* Proxies API routes to Python server at localhost:{api_port}
|
|
588
631
|
*/
|
|
589
632
|
export default defineConfig({{
|
|
633
|
+
define: {{
|
|
634
|
+
'globalThis.__JAC_API_BASE_URL__': '"{api_base_url}"',
|
|
635
|
+
}},
|
|
590
636
|
plugins: [react()],
|
|
591
637
|
root: buildDir,
|
|
592
638
|
publicDir: false,
|
|
639
|
+
appType: 'spa',
|
|
593
640
|
build: {{
|
|
594
641
|
sourcemap: true, // Enable source maps for better error messages
|
|
595
642
|
}},
|
|
@@ -615,6 +662,10 @@ export default defineConfig({{
|
|
|
615
662
|
target: "http://localhost:{api_port}",
|
|
616
663
|
changeOrigin: true,
|
|
617
664
|
}},
|
|
665
|
+
"/static": {{
|
|
666
|
+
target: "http://localhost:{api_port}",
|
|
667
|
+
changeOrigin: true,
|
|
668
|
+
}},
|
|
618
669
|
}},
|
|
619
670
|
}},
|
|
620
671
|
resolve: {{
|
{jac_client-0.2.11 → jac_client-0.2.13}/jac_client/plugin/src/targets/desktop/sidecar/main.py
RENAMED
|
@@ -11,7 +11,7 @@ Usage:
|
|
|
11
11
|
|
|
12
12
|
Options:
|
|
13
13
|
--module-path PATH Path to the .jac module file (default: main.jac)
|
|
14
|
-
--port PORT Port to bind the API server (default: 8000)
|
|
14
|
+
--port PORT Port to bind the API server (default: 8000, 0 = auto)
|
|
15
15
|
--base-path PATH Base path for the project (default: current directory)
|
|
16
16
|
--host HOST Host to bind to (default: 127.0.0.1)
|
|
17
17
|
--help Show this help message
|
|
@@ -20,10 +20,16 @@ Options:
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
22
|
import argparse
|
|
23
|
+
import socket
|
|
23
24
|
import sys
|
|
24
25
|
from pathlib import Path
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
|
|
28
|
+
def _find_free_port(host: str = "127.0.0.1") -> int:
|
|
29
|
+
"""Find and return a free port on the given host."""
|
|
30
|
+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
31
|
+
s.bind((host, 0))
|
|
32
|
+
return s.getsockname()[1]
|
|
27
33
|
|
|
28
34
|
|
|
29
35
|
def main():
|
|
@@ -41,7 +47,7 @@ def main():
|
|
|
41
47
|
"--port",
|
|
42
48
|
type=int,
|
|
43
49
|
default=8000,
|
|
44
|
-
help="Port to bind the API server (default: 8000)",
|
|
50
|
+
help="Port to bind the API server (default: 8000, 0 = auto-assign free port)",
|
|
45
51
|
)
|
|
46
52
|
parser.add_argument(
|
|
47
53
|
"--base-path",
|
|
@@ -58,6 +64,10 @@ def main():
|
|
|
58
64
|
|
|
59
65
|
args = parser.parse_args()
|
|
60
66
|
|
|
67
|
+
port = args.port
|
|
68
|
+
if port == 0:
|
|
69
|
+
port = _find_free_port(args.host)
|
|
70
|
+
|
|
61
71
|
# Determine base path
|
|
62
72
|
if args.base_path:
|
|
63
73
|
base_path = Path(args.base_path).resolve()
|
|
@@ -75,8 +85,9 @@ def main():
|
|
|
75
85
|
module_path = base_path / module_path
|
|
76
86
|
|
|
77
87
|
if not module_path.exists():
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
# Console not yet available (jaclang not imported)
|
|
89
|
+
sys.stderr.write(f"Error: Module file not found: {module_path}\n")
|
|
90
|
+
sys.stderr.write(f" Base path: {base_path}\n")
|
|
80
91
|
sys.exit(1)
|
|
81
92
|
|
|
82
93
|
# Extract module name (without .jac extension)
|
|
@@ -88,25 +99,25 @@ def main():
|
|
|
88
99
|
# Import jaclang (must be installed via pip)
|
|
89
100
|
from jaclang.pycore.runtime import JacRuntime as Jac
|
|
90
101
|
except ImportError as e:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
102
|
+
# Console not available (jaclang import failed)
|
|
103
|
+
sys.stderr.write(f"Error: Failed to import Jac runtime: {e}\n")
|
|
104
|
+
sys.stderr.write(" Make sure jaclang is installed: pip install jaclang\n")
|
|
95
105
|
sys.exit(1)
|
|
96
106
|
|
|
107
|
+
# Get the console now that jaclang is available
|
|
108
|
+
from jaclang.cli.console import console
|
|
109
|
+
|
|
97
110
|
# Initialize Jac runtime
|
|
98
111
|
try:
|
|
99
112
|
# Import the module
|
|
100
113
|
Jac.jac_import(target=module_name, base_path=str(module_base), lng="jac")
|
|
101
114
|
if Jac.program.errors_had:
|
|
102
|
-
console.
|
|
115
|
+
console.error("Failed to compile module:")
|
|
103
116
|
for error in Jac.program.errors_had:
|
|
104
|
-
console.print(f" {error}",
|
|
117
|
+
console.print(f" {error}", style="error")
|
|
105
118
|
sys.exit(1)
|
|
106
119
|
except Exception as e:
|
|
107
|
-
console.
|
|
108
|
-
f"Error: Failed to load module '{module_name}': {e}", file=sys.stderr
|
|
109
|
-
)
|
|
120
|
+
console.error(f"Failed to load module '{module_name}': {e}")
|
|
110
121
|
import traceback
|
|
111
122
|
|
|
112
123
|
traceback.print_exc()
|
|
@@ -117,23 +128,31 @@ def main():
|
|
|
117
128
|
# Get server class (allows plugins like jac-scale to provide enhanced server)
|
|
118
129
|
server_class = Jac.get_api_server_class()
|
|
119
130
|
server = server_class(
|
|
120
|
-
module_name=module_name, port=
|
|
131
|
+
module_name=module_name, port=port, base_path=str(base_path)
|
|
121
132
|
)
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
console.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
# MUST be raw stdout — Tauri host reads this line to discover the port.
|
|
135
|
+
# Cannot use console here; Tauri parses this exact format.
|
|
136
|
+
sys.stdout.write(f"JAC_SIDECAR_PORT={port}\n")
|
|
137
|
+
sys.stdout.flush()
|
|
138
|
+
|
|
139
|
+
# stderr: Tauri drops the stdout pipe after reading the port marker,
|
|
140
|
+
# so any further stdout writes raise BrokenPipeError.
|
|
141
|
+
console.print("Jac Sidecar starting...", style="bold")
|
|
142
|
+
console.print(f" Module: {module_name}", style="muted")
|
|
143
|
+
console.print(f" Base path: {base_path}", style="muted")
|
|
144
|
+
console.print(f" Server: http://{args.host}:{port}", style="muted")
|
|
145
|
+
console.print("")
|
|
128
146
|
|
|
129
147
|
# Start the server (blocks until interrupted)
|
|
130
|
-
|
|
148
|
+
# no_client=True: client bundle is already embedded in the Tauri webview
|
|
149
|
+
server.start(dev=False, no_client=True)
|
|
131
150
|
|
|
132
151
|
except KeyboardInterrupt:
|
|
133
|
-
console.print("\nShutting down sidecar...")
|
|
152
|
+
console.print("\nShutting down sidecar...", style="muted")
|
|
134
153
|
sys.exit(0)
|
|
135
154
|
except Exception as e:
|
|
136
|
-
console.
|
|
155
|
+
console.error(f"Server failed to start: {e}")
|
|
137
156
|
import traceback
|
|
138
157
|
|
|
139
158
|
traceback.print_exc()
|
|
@@ -28,10 +28,12 @@ class DesktopTarget(ClientTarget) {
|
|
|
28
28
|
) -> Path;
|
|
29
29
|
|
|
30
30
|
"""Start desktop dev server - start web dev server and launch tauri dev."""
|
|
31
|
-
override def dev(
|
|
31
|
+
override def dev(
|
|
32
|
+
self: DesktopTarget, entry_file: Path, project_dir: Path, api_port: int = 8000
|
|
33
|
+
) -> None;
|
|
32
34
|
|
|
33
35
|
"""Start desktop app - build web bundle and launch Tauri with built bundle."""
|
|
34
36
|
override def start(
|
|
35
|
-
self: DesktopTarget, entry_file: Path, project_dir: Path
|
|
37
|
+
self: DesktopTarget, entry_file: Path, project_dir: Path, api_port: int = 8000
|
|
36
38
|
) -> None;
|
|
37
39
|
}
|