jac-client 0.2.8__py3-none-any.whl → 0.2.11__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.
- jac_client/examples/all-in-one/button.jac +4 -3
- jac_client/examples/all-in-one/components/CategoryFilter.jac +36 -24
- jac_client/examples/all-in-one/components/Header.jac +12 -8
- jac_client/examples/all-in-one/components/ProfitOverview.jac +49 -35
- jac_client/examples/all-in-one/components/Summary.jac +59 -36
- jac_client/examples/all-in-one/components/TransactionForm.jac +142 -112
- jac_client/examples/all-in-one/components/TransactionItem.jac +37 -30
- jac_client/examples/all-in-one/components/TransactionList.jac +33 -26
- jac_client/examples/all-in-one/components/button.jac +4 -3
- jac_client/examples/all-in-one/components/navigation.jac +111 -117
- jac_client/examples/all-in-one/constants/categories.jac +23 -24
- jac_client/examples/all-in-one/constants/clients.jac +7 -8
- jac_client/examples/all-in-one/context/BudgetContext.jac +9 -6
- jac_client/examples/all-in-one/hooks/useBudget.jac +18 -12
- jac_client/examples/all-in-one/hooks/useLocalStorage.jac +14 -13
- jac_client/examples/all-in-one/main.jac +542 -0
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +26 -12
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +43 -12
- jac_client/examples/all-in-one/pages/LandingPage.jac +113 -90
- jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +65 -0
- jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +675 -0
- jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
- jac_client/examples/all-in-one/pages/nestedDemo.jac +44 -51
- jac_client/examples/all-in-one/pages/notFound.jac +15 -21
- jac_client/examples/all-in-one/pages/signupPage.jac +113 -119
- jac_client/examples/all-in-one/utils/formatters.jac +5 -8
- jac_client/examples/asset-serving/css-with-image/main.jac +92 -0
- jac_client/examples/asset-serving/image-asset/main.jac +56 -0
- jac_client/examples/asset-serving/import-alias/main.jac +109 -0
- jac_client/examples/basic/main.jac +23 -0
- jac_client/examples/basic-auth/main.jac +363 -0
- jac_client/examples/basic-auth-with-router/main.jac +451 -0
- jac_client/examples/basic-full-stack/main.jac +362 -0
- jac_client/examples/css-styling/js-styling/main.jac +63 -0
- jac_client/examples/css-styling/material-ui/main.jac +122 -0
- jac_client/examples/css-styling/pure-css/main.jac +55 -0
- jac_client/examples/css-styling/sass-example/main.jac +55 -0
- jac_client/examples/css-styling/styled-components/main.jac +62 -0
- jac_client/examples/css-styling/tailwind-example/main.jac +74 -0
- jac_client/examples/full-stack-with-auth/main.jac +696 -0
- jac_client/examples/little-x/main.jac +681 -0
- jac_client/examples/little-x/src/submit-button.jac +15 -14
- jac_client/examples/nested-folders/nested-advance/main.jac +26 -0
- jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +4 -6
- jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +9 -13
- jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +29 -32
- jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +12 -18
- jac_client/examples/nested-folders/nested-basic/{src/app.jac → main.jac} +7 -5
- jac_client/examples/nested-folders/nested-basic/src/button.jac +4 -3
- jac_client/examples/nested-folders/nested-basic/src/components/button.jac +4 -3
- jac_client/examples/ts-support/main.jac +35 -0
- jac_client/examples/with-router/main.jac +286 -0
- jac_client/plugin/cli.jac +491 -411
- jac_client/plugin/client.jac +25 -0
- jac_client/plugin/client_runtime.cl.jac +10 -4
- jac_client/plugin/impl/client.impl.jac +96 -55
- jac_client/plugin/impl/client_runtime.impl.jac +155 -1
- jac_client/plugin/plugin_config.jac +211 -29
- jac_client/plugin/src/__init__.jac +0 -2
- jac_client/plugin/src/compiler.jac +0 -1
- jac_client/plugin/src/config_loader.jac +1 -0
- jac_client/plugin/src/desktop_config.jac +31 -0
- jac_client/plugin/src/impl/compiler.impl.jac +49 -17
- jac_client/plugin/src/impl/config_loader.impl.jac +8 -0
- jac_client/plugin/src/impl/desktop_config.impl.jac +191 -0
- jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
- jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
- jac_client/plugin/src/impl/vite_bundler.impl.jac +191 -64
- jac_client/plugin/src/targets/desktop/sidecar/main.py +144 -0
- jac_client/plugin/src/targets/desktop_target.jac +37 -0
- jac_client/plugin/src/targets/impl/desktop_target.impl.jac +2347 -0
- jac_client/plugin/src/targets/impl/registry.impl.jac +64 -0
- jac_client/plugin/src/targets/impl/web_target.impl.jac +157 -0
- jac_client/plugin/src/targets/register.jac +21 -0
- jac_client/plugin/src/targets/registry.jac +87 -0
- jac_client/plugin/src/targets/web_target.jac +35 -0
- jac_client/plugin/src/vite_bundler.jac +6 -0
- jac_client/plugin/utils/__init__.jac +3 -0
- jac_client/plugin/utils/bun_installer.jac +16 -0
- jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
- jac_client/templates/client.jacpack +72 -0
- jac_client/templates/fullstack.jacpack +61 -0
- jac_client/tests/conftest.py +103 -47
- jac_client/tests/fixtures/spawn_test/app.jac +49 -52
- jac_client/tests/fixtures/with-ts/app.jac +27 -27
- jac_client/tests/test_cli.py +182 -71
- jac_client/tests/test_e2e.py +232 -0
- jac_client/tests/test_helpers.py +58 -0
- jac_client/tests/test_it.py +91 -135
- jac_client/tests/test_it_desktop.py +891 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/METADATA +6 -6
- jac_client-0.2.11.dist-info/RECORD +113 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/WHEEL +1 -1
- jac_client/examples/all-in-one/app.jac +0 -573
- jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +0 -70
- jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +0 -552
- jac_client/examples/asset-serving/css-with-image/src/app.jac +0 -88
- jac_client/examples/asset-serving/image-asset/src/app.jac +0 -55
- jac_client/examples/asset-serving/import-alias/src/app.jac +0 -111
- jac_client/examples/basic/src/app.jac +0 -21
- jac_client/examples/basic-auth/src/app.jac +0 -371
- jac_client/examples/basic-auth-with-router/src/app.jac +0 -464
- jac_client/examples/basic-full-stack/src/app.jac +0 -359
- jac_client/examples/css-styling/js-styling/src/app.jac +0 -84
- jac_client/examples/css-styling/material-ui/src/app.jac +0 -122
- jac_client/examples/css-styling/pure-css/src/app.jac +0 -64
- jac_client/examples/css-styling/sass-example/src/app.jac +0 -64
- jac_client/examples/css-styling/styled-components/src/app.jac +0 -71
- jac_client/examples/css-styling/tailwind-example/src/app.jac +0 -63
- jac_client/examples/full-stack-with-auth/src/app.jac +0 -722
- jac_client/examples/little-x/src/app.jac +0 -719
- jac_client/examples/nested-folders/nested-advance/src/app.jac +0 -35
- jac_client/examples/ts-support/src/app.jac +0 -35
- jac_client/examples/with-router/src/app.jac +0 -323
- jac_client/plugin/src/babel_processor.jac +0 -18
- jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
- jac_client-0.2.8.dist-info/RECORD +0 -97
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/entry_points.txt +0 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Implementation of Desktop target configuration loader."""
|
|
2
|
+
import from pathlib { Path }
|
|
3
|
+
import from typing { Any }
|
|
4
|
+
import from jaclang.project.config { JacConfig, get_config }
|
|
5
|
+
import from jaclang.project.plugin_config { deep_merge }
|
|
6
|
+
import from jaclang.cli.console { console }
|
|
7
|
+
|
|
8
|
+
"""Initialize DesktopConfig with project directory."""
|
|
9
|
+
impl DesktopConfig.init(self: DesktopConfig, project_dir: Path | None = None) -> None {
|
|
10
|
+
if project_dir is None {
|
|
11
|
+
self.project_dir = Path.cwd();
|
|
12
|
+
} else {
|
|
13
|
+
self.project_dir = project_dir;
|
|
14
|
+
}
|
|
15
|
+
self._config = None;
|
|
16
|
+
self._jac_config = None;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
"""Get default configuration structure for desktop target."""
|
|
20
|
+
impl DesktopConfig.get_default_config(self: DesktopConfig) -> dict[str, Any] {
|
|
21
|
+
# Try to get project name/version from JacConfig for defaults
|
|
22
|
+
# If config is not available, use fallback defaults
|
|
23
|
+
project_name = "my-jac-app";
|
|
24
|
+
project_version = "1.0.0";
|
|
25
|
+
try {
|
|
26
|
+
jac_config = self._get_jac_config();
|
|
27
|
+
if jac_config and jac_config.project {
|
|
28
|
+
project_name = jac_config.project.name or project_name;
|
|
29
|
+
project_version = jac_config.project.version or project_version;
|
|
30
|
+
}
|
|
31
|
+
} except Exception {
|
|
32
|
+
# If config loading fails, use defaults
|
|
33
|
+
console.warning("Failed to load JacConfig, using fallback defaults");
|
|
34
|
+
}
|
|
35
|
+
# Generate identifier from project name
|
|
36
|
+
identifier = _generate_identifier(project_name);
|
|
37
|
+
return {
|
|
38
|
+
'name': project_name,
|
|
39
|
+
'identifier': identifier,
|
|
40
|
+
'version': project_version,
|
|
41
|
+
'window': {
|
|
42
|
+
'title': project_name,
|
|
43
|
+
'width': 1200,
|
|
44
|
+
'height': 800,
|
|
45
|
+
'min_width': 800,
|
|
46
|
+
'min_height': 600,
|
|
47
|
+
'resizable': True,
|
|
48
|
+
'fullscreen': False
|
|
49
|
+
},
|
|
50
|
+
'platforms': {'windows': True, 'macos': True, 'linux': True},
|
|
51
|
+
'features': {
|
|
52
|
+
'system_tray': False,
|
|
53
|
+
'auto_update': False,
|
|
54
|
+
'notifications': False
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
"""Get or load the core JacConfig instance."""
|
|
60
|
+
impl DesktopConfig._get_jac_config(self: DesktopConfig) -> JacConfig {
|
|
61
|
+
if self._jac_config is None {
|
|
62
|
+
self._jac_config = get_config();
|
|
63
|
+
if self._jac_config is None {
|
|
64
|
+
raise RuntimeError(
|
|
65
|
+
"No jac.toml found. Run 'jac create' to create a project."
|
|
66
|
+
) ;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return self._jac_config;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
"""Load configuration from jac.toml, merging with defaults."""
|
|
73
|
+
impl DesktopConfig.load(self: DesktopConfig) -> dict[str, Any] {
|
|
74
|
+
if self._config is not None {
|
|
75
|
+
return self._config;
|
|
76
|
+
}
|
|
77
|
+
default_config = self.get_default_config();
|
|
78
|
+
# Try to get [desktop] section from jac.toml
|
|
79
|
+
desktop_config = {};
|
|
80
|
+
try {
|
|
81
|
+
jac_config = self._get_jac_config();
|
|
82
|
+
# Get [desktop] section from raw TOML data
|
|
83
|
+
# The [desktop] section is not under [plugins], so we access it directly
|
|
84
|
+
if jac_config and jac_config._raw_data {
|
|
85
|
+
raw_data = jac_config._raw_data;
|
|
86
|
+
desktop_config = raw_data.get('desktop', {});
|
|
87
|
+
}
|
|
88
|
+
} except Exception {
|
|
89
|
+
# If config loading fails, use defaults only
|
|
90
|
+
console.warning("Failed to load JacConfig, using fallback defaults");
|
|
91
|
+
}
|
|
92
|
+
# Deep merge defaults with user configuration
|
|
93
|
+
if desktop_config {
|
|
94
|
+
self._config = deep_merge(default_config, desktop_config);
|
|
95
|
+
} else {
|
|
96
|
+
self._config = default_config;
|
|
97
|
+
}
|
|
98
|
+
return self._config;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
"""Get desktop configuration (name, identifier, version)."""
|
|
102
|
+
impl DesktopConfig.get_desktop_config(self: DesktopConfig) -> dict[str, Any] {
|
|
103
|
+
config = self.load();
|
|
104
|
+
return {
|
|
105
|
+
'name': config.get('name', ''),
|
|
106
|
+
'identifier': config.get('identifier', ''),
|
|
107
|
+
'version': config.get('version', '1.0.0')
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
"""Get window configuration."""
|
|
112
|
+
impl DesktopConfig.get_window_config(self: DesktopConfig) -> dict[str, Any] {
|
|
113
|
+
config = self.load();
|
|
114
|
+
return config.get('window', {});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
"""Get platforms configuration."""
|
|
118
|
+
impl DesktopConfig.get_platforms_config(self: DesktopConfig) -> dict[str, Any] {
|
|
119
|
+
config = self.load();
|
|
120
|
+
return config.get('platforms', {});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
"""Get features configuration."""
|
|
124
|
+
impl DesktopConfig.get_features_config(self: DesktopConfig) -> dict[str, Any] {
|
|
125
|
+
config = self.load();
|
|
126
|
+
return config.get('features', {});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
"""Validate desktop configuration."""
|
|
130
|
+
impl DesktopConfig.validate(self: DesktopConfig) -> None {
|
|
131
|
+
config = self.load();
|
|
132
|
+
# Required fields
|
|
133
|
+
name = config.get('name', '');
|
|
134
|
+
if not name {
|
|
135
|
+
raise ValueError(
|
|
136
|
+
"Desktop configuration error: 'name' is required in [desktop] section"
|
|
137
|
+
) ;
|
|
138
|
+
}
|
|
139
|
+
identifier = config.get('identifier', '');
|
|
140
|
+
if not identifier {
|
|
141
|
+
raise ValueError(
|
|
142
|
+
"Desktop configuration error: 'identifier' is required in [desktop] section"
|
|
143
|
+
) ;
|
|
144
|
+
}
|
|
145
|
+
# Validate identifier format (should be reverse domain notation)
|
|
146
|
+
if not _is_valid_identifier(identifier) {
|
|
147
|
+
console.warning(
|
|
148
|
+
f"Desktop identifier '{identifier}' may not be valid. Use reverse domain notation (e.g., 'com.example.myapp')"
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
# Validate window dimensions
|
|
152
|
+
window = config.get('window', {});
|
|
153
|
+
width = window.get('width', 1200);
|
|
154
|
+
height = window.get('height', 800);
|
|
155
|
+
min_width = window.get('min_width', 800);
|
|
156
|
+
min_height = window.get('min_height', 600);
|
|
157
|
+
if min_width > width {
|
|
158
|
+
raise ValueError(
|
|
159
|
+
f"Desktop configuration error: window.min_width ({min_width}) cannot be greater than window.width ({width})"
|
|
160
|
+
) ;
|
|
161
|
+
}
|
|
162
|
+
if min_height > height {
|
|
163
|
+
raise ValueError(
|
|
164
|
+
f"Desktop configuration error: window.min_height ({min_height}) cannot be greater than window.height ({height})"
|
|
165
|
+
) ;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
"""Generate identifier from project name."""
|
|
170
|
+
def _generate_identifier(name: str) -> str {
|
|
171
|
+
# Convert to lowercase, replace spaces/special chars with dots
|
|
172
|
+
import re;
|
|
173
|
+
# Remove special characters, keep alphanumeric, dots, hyphens
|
|
174
|
+
cleaned = re.sub(r'[^a-zA-Z0-9.\-]', '', name.lower());
|
|
175
|
+
# Replace multiple dots/hyphens with single dot
|
|
176
|
+
cleaned = re.sub(r'[.\-]+', '.', cleaned);
|
|
177
|
+
# Remove leading/trailing dots
|
|
178
|
+
cleaned = cleaned.strip('.');
|
|
179
|
+
# If empty or doesn't look like reverse domain, prefix with 'com.'
|
|
180
|
+
if not cleaned or not '.' in cleaned {
|
|
181
|
+
cleaned = f"com.{cleaned}" if cleaned else "com.myapp";
|
|
182
|
+
}
|
|
183
|
+
return cleaned;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
"""Check if identifier is valid (reverse domain notation)."""
|
|
187
|
+
def _is_valid_identifier(identifier: str) -> bool {
|
|
188
|
+
import re;
|
|
189
|
+
# Should be like: com.example.myapp (at least one dot, alphanumeric + dots)
|
|
190
|
+
return bool(re.match(r'^[a-z0-9]+(\.[a-z0-9]+)+$', identifier.lower()));
|
|
191
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"""Add runtime imports to compiled JS code."""
|
|
2
2
|
|
|
3
3
|
impl JacToJSCompiler.add_runtime_imports(self: JacToJSCompiler, js_code: str) -> str {
|
|
4
|
-
|
|
4
|
+
# Skip adding import if this file IS the runtime (defines __jacJsx itself)
|
|
5
|
+
if "function __jacJsx(" in js_code {
|
|
6
|
+
return js_code;
|
|
7
|
+
}
|
|
8
|
+
jac_jsx_import = 'import {__jacJsx, __jacSpawn} from "@jac/runtime";';
|
|
5
9
|
return f"{jac_jsx_import}\n{js_code}";
|
|
6
10
|
}
|
|
7
11
|
|
|
@@ -33,39 +33,39 @@ impl PackageInstaller.uninstall_package(
|
|
|
33
33
|
}
|
|
34
34
|
# Save the updated config
|
|
35
35
|
self.config_loader.save();
|
|
36
|
-
# Regenerate package.json and run
|
|
36
|
+
# Regenerate package.json and run bun install to actually remove the package
|
|
37
37
|
self._regenerate_and_install();
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
"""Regenerate package.json from jac.toml and run
|
|
40
|
+
"""Regenerate package.json from jac.toml and run bun install."""
|
|
41
41
|
impl PackageInstaller._regenerate_and_install(self: PackageInstaller) -> None {
|
|
42
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
43
|
+
# Ensure bun is available before proceeding
|
|
44
|
+
if not ensure_bun_available() {
|
|
45
|
+
raise ClientBundleError('Bun is required. Install manually: https://bun.sh') from None ;
|
|
46
|
+
}
|
|
42
47
|
# Regenerate package.json from updated jac.toml
|
|
43
48
|
bundler = ViteBundler(self.project_dir);
|
|
44
49
|
bundler.create_package_json();
|
|
45
|
-
# Ensure root package.json exists temporarily for
|
|
50
|
+
# Ensure root package.json exists temporarily for bun commands
|
|
46
51
|
bundler._ensure_root_package_json();
|
|
47
52
|
try {
|
|
48
|
-
# Run
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
cwd=self.project_dir,
|
|
52
|
-
check=True,
|
|
53
|
-
capture_output=True,
|
|
54
|
-
text=True
|
|
53
|
+
# Run bun install to actually install the packages
|
|
54
|
+
print("\n ⏳ Installing packages...\n", flush=True);
|
|
55
|
+
result = subprocess.run(
|
|
56
|
+
['bun', 'install'], cwd=self.project_dir, check=False, text=True
|
|
55
57
|
);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
'npm command not found. Ensure Node.js and npm are installed.'
|
|
61
|
-
) from None ;
|
|
58
|
+
if result.returncode != 0 {
|
|
59
|
+
raise ClientBundleError('Failed to install packages (see output above)') ;
|
|
60
|
+
}
|
|
61
|
+
print("\n ✔ Packages installed", flush=True);
|
|
62
62
|
} finally {
|
|
63
|
-
# Always clean up root package.json and move
|
|
63
|
+
# Always clean up root package.json and move bun.lockb
|
|
64
64
|
bundler._cleanup_root_package_files();
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
"""Install all packages from jac.toml (regenerate package.json and run
|
|
68
|
+
"""Install all packages from jac.toml (regenerate package.json and run bun install)."""
|
|
69
69
|
impl PackageInstaller.install_all(self: PackageInstaller) -> None {
|
|
70
70
|
if not self.config_file.exists() {
|
|
71
71
|
raise ClientBundleError(
|
|
@@ -93,11 +93,11 @@ impl PackageInstaller.install_package(
|
|
|
93
93
|
self.config_loader.add_dependency(package_name, package_version, is_dev);
|
|
94
94
|
# Save the updated config
|
|
95
95
|
self.config_loader.save();
|
|
96
|
-
# Regenerate package.json and install the package via
|
|
96
|
+
# Regenerate package.json and install the package via bun
|
|
97
97
|
self._regenerate_and_install();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
"""Handles installing
|
|
100
|
+
"""Handles installing packages by updating jac.toml."""
|
|
101
101
|
impl PackageInstaller.init(self: PackageInstaller, project_dir: Path) {
|
|
102
102
|
self.project_dir = project_dir;
|
|
103
103
|
self.config_loader = JacClientConfig(project_dir);
|