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
|
@@ -5,10 +5,13 @@ configuration system, registering:
|
|
|
5
5
|
- Plugin metadata (name, version)
|
|
6
6
|
- Config schema for [plugins.client] section
|
|
7
7
|
- npm dependency type for [dependencies.npm] section
|
|
8
|
+
- Project templates (client, fullstack)
|
|
8
9
|
"""
|
|
9
10
|
|
|
11
|
+
import os;
|
|
10
12
|
import subprocess;
|
|
11
13
|
import sys;
|
|
14
|
+
import json;
|
|
12
15
|
import from pathlib { Path }
|
|
13
16
|
import from typing { Any }
|
|
14
17
|
import from jaclang.pycore.runtime { hookimpl }
|
|
@@ -68,6 +71,11 @@ class JacClientPluginConfig {
|
|
|
68
71
|
"type": "dict",
|
|
69
72
|
"default": {},
|
|
70
73
|
"description": "TypeScript configuration overrides"
|
|
74
|
+
},
|
|
75
|
+
"configs": {
|
|
76
|
+
"type": "dict",
|
|
77
|
+
"default": {},
|
|
78
|
+
"description": "Generate config files for npm packages. Keys are config names (e.g., 'postcss', 'tailwind'), values are the config objects to export."
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
81
|
};
|
|
@@ -79,15 +87,194 @@ class JacClientPluginConfig {
|
|
|
79
87
|
return {
|
|
80
88
|
"name": "npm",
|
|
81
89
|
"dev_name": "npm.dev",
|
|
82
|
-
"cli_flag": "--
|
|
90
|
+
"cli_flag": "--npm",
|
|
83
91
|
"install_dir": ".jac/client/configs",
|
|
84
92
|
"install_handler": _npm_install_handler,
|
|
85
93
|
"install_all_handler": _npm_install_all_handler,
|
|
86
94
|
"remove_handler": _npm_remove_handler
|
|
87
95
|
};
|
|
88
96
|
}
|
|
97
|
+
|
|
98
|
+
"""Register the client and fullstack project templates."""
|
|
99
|
+
@hookimpl
|
|
100
|
+
static def register_project_template -> list[dict[str, Any]] {
|
|
101
|
+
templates: list[dict[str, Any]] = [];
|
|
102
|
+
|
|
103
|
+
# Load templates from bundled JSON files
|
|
104
|
+
for template_name in ["client", "fullstack"] {
|
|
105
|
+
template = _load_template(template_name);
|
|
106
|
+
if template {
|
|
107
|
+
templates.append(template);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return templates;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# ===============================================================================
|
|
116
|
+
# Template Loader
|
|
117
|
+
# ===============================================================================
|
|
118
|
+
"""Load a template from bundled JSON file."""
|
|
119
|
+
def _load_template(template_name: str) -> dict[str, Any] | None {
|
|
120
|
+
# Find the template JSON file relative to this module
|
|
121
|
+
# plugin_config.jac is in jac_client/plugin/, so .parent.parent = jac_client/
|
|
122
|
+
module_dir = Path(__file__).parent.parent; # jac_client directory
|
|
123
|
+
template_path = module_dir / "templates" / f"{template_name}.jacpack";
|
|
124
|
+
|
|
125
|
+
if not template_path.exists() {
|
|
126
|
+
# Fallback: look in installed package location
|
|
127
|
+
import from importlib.resources { files }
|
|
128
|
+
try {
|
|
129
|
+
package_files = files("jac_client");
|
|
130
|
+
template_path = Path(str(package_files)) / "templates" / f"{template_name}.jacpack";
|
|
131
|
+
} except Exception {
|
|
132
|
+
return None;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if not template_path.exists() {
|
|
137
|
+
return None;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
with open(template_path, "r") as f {
|
|
142
|
+
data = json.load(f);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
# Attach the post_create hook
|
|
146
|
+
data["post_create"] = _post_create_client;
|
|
147
|
+
|
|
148
|
+
return data;
|
|
149
|
+
} except Exception as e {
|
|
150
|
+
print(
|
|
151
|
+
f"Warning: Could not load {template_name} template: {e}", file=sys.stderr
|
|
152
|
+
);
|
|
153
|
+
return None;
|
|
154
|
+
}
|
|
89
155
|
}
|
|
90
156
|
|
|
157
|
+
# ===============================================================================
|
|
158
|
+
# Post-create Hook for Client Template
|
|
159
|
+
# ===============================================================================
|
|
160
|
+
"""Post-create hook to ensure Bun is installed and optionally install packages."""
|
|
161
|
+
def _post_create_client(project_path: Path, project_name: str) -> None {
|
|
162
|
+
import from jac_client.plugin.src.vite_bundler { ViteBundler }
|
|
163
|
+
import from jaclang.cli.console { console }
|
|
164
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
165
|
+
|
|
166
|
+
# First, ensure Bun is installed (prompt to install if not)
|
|
167
|
+
console.print();
|
|
168
|
+
if not ensure_bun_available() {
|
|
169
|
+
console.warning("Bun is required for client development");
|
|
170
|
+
console.print(" After installing Bun, run: jac add --cl\n", style="muted");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
console.print(" ✔ Bun is installed", style="success");
|
|
175
|
+
|
|
176
|
+
# Check if package installation should be skipped
|
|
177
|
+
if os.environ.get("JAC_CLIENT_SKIP_NPM_INSTALL") {
|
|
178
|
+
console.print(
|
|
179
|
+
"\n ⏭ Skipping package installation (JAC_CLIENT_SKIP_NPM_INSTALL is set)",
|
|
180
|
+
style="muted"
|
|
181
|
+
);
|
|
182
|
+
console.print(
|
|
183
|
+
" Run 'jac add --npm' when ready to install packages.\n", style="muted"
|
|
184
|
+
);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.print();
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
# Verify jac.toml exists
|
|
192
|
+
toml_path = project_path / "jac.toml";
|
|
193
|
+
if not toml_path.exists() {
|
|
194
|
+
print(
|
|
195
|
+
"Warning: jac.toml not found, skipping package installation",
|
|
196
|
+
file=sys.stderr
|
|
197
|
+
);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# Create ViteBundler instance
|
|
202
|
+
bundler = ViteBundler(project_path);
|
|
203
|
+
|
|
204
|
+
# Generate package.json with default packages
|
|
205
|
+
bundler.create_package_json(project_name=project_name);
|
|
206
|
+
|
|
207
|
+
# Ensure .jac/client directory exists
|
|
208
|
+
client_dir = bundler._get_client_dir();
|
|
209
|
+
client_dir.mkdir(parents=True, exist_ok=True);
|
|
210
|
+
|
|
211
|
+
# Copy package.json to .jac/client/ for bun install
|
|
212
|
+
configs_package_json = client_dir / 'configs' / 'package.json';
|
|
213
|
+
build_package_json = client_dir / 'package.json';
|
|
214
|
+
|
|
215
|
+
if not configs_package_json.exists() {
|
|
216
|
+
print(
|
|
217
|
+
"Warning: package.json was not generated, skipping package installation",
|
|
218
|
+
file=sys.stderr
|
|
219
|
+
);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
shutil.copy2(configs_package_json, build_package_json);
|
|
224
|
+
|
|
225
|
+
# Run bun install (ensure bun is available first)
|
|
226
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
227
|
+
if not ensure_bun_available() {
|
|
228
|
+
console.warning("Bun is required. Install manually: https://bun.sh");
|
|
229
|
+
console.print(
|
|
230
|
+
" 💡 You can install packages later with: jac add --cl\n",
|
|
231
|
+
style="muted"
|
|
232
|
+
);
|
|
233
|
+
# Clean up temporary package.json
|
|
234
|
+
if build_package_json.exists() {
|
|
235
|
+
build_package_json.unlink();
|
|
236
|
+
}
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
console.print("\n ⏳ Installing packages...\n", style="cyan");
|
|
242
|
+
subprocess.run(['bun', 'install'], cwd=client_dir, check=True, timeout=300);
|
|
243
|
+
|
|
244
|
+
# Move bun.lockb to configs/ if it was created
|
|
245
|
+
build_bun_lockb = client_dir / 'bun.lockb';
|
|
246
|
+
configs_bun_lockb = client_dir / 'configs' / 'bun.lockb';
|
|
247
|
+
if build_bun_lockb.exists() {
|
|
248
|
+
if configs_bun_lockb.exists() {
|
|
249
|
+
configs_bun_lockb.unlink();
|
|
250
|
+
}
|
|
251
|
+
shutil.move(str(build_bun_lockb), str(configs_bun_lockb));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.print(" ✔ Packages installed", style="success");
|
|
255
|
+
} except subprocess.CalledProcessError as e {
|
|
256
|
+
console.warning(f"Failed to install packages: {e}");
|
|
257
|
+
console.print(
|
|
258
|
+
" 💡 You can install packages later with: jac add --cl\n",
|
|
259
|
+
style="muted"
|
|
260
|
+
);
|
|
261
|
+
} finally {
|
|
262
|
+
# Clean up temporary package.json
|
|
263
|
+
if build_package_json.exists() {
|
|
264
|
+
build_package_json.unlink();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} except Exception as e {
|
|
268
|
+
console.warning(f"Could not install default packages: {e}");
|
|
269
|
+
console.print(
|
|
270
|
+
" 💡 You can install packages later with: jac add --cl\n", style="muted"
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
# ===============================================================================
|
|
276
|
+
# NPM Dependency Handlers
|
|
277
|
+
# ===============================================================================
|
|
91
278
|
"""Install an npm package."""
|
|
92
279
|
def _npm_install_handler(
|
|
93
280
|
config: JacConfig,
|
|
@@ -101,15 +288,13 @@ def _npm_install_handler(
|
|
|
101
288
|
raise RuntimeError("No project root found") ;
|
|
102
289
|
}
|
|
103
290
|
|
|
104
|
-
project_dir = config.project_root;
|
|
105
|
-
|
|
106
291
|
# Add to config (core JacConfig handles this)
|
|
107
|
-
package_version = version or "latest";
|
|
292
|
+
package_version: str = version or "latest";
|
|
108
293
|
config.add_dependency(package_name, package_version, dev=is_dev, dep_type="npm");
|
|
109
294
|
config.save();
|
|
110
295
|
|
|
111
296
|
# Generate package.json and run npm install
|
|
112
|
-
_regenerate_and_install(
|
|
297
|
+
_regenerate_and_install(Path(str(config.project_root)));
|
|
113
298
|
}
|
|
114
299
|
|
|
115
300
|
"""Install all npm packages from jac.toml."""
|
|
@@ -118,7 +303,7 @@ def _npm_install_all_handler(config: JacConfig) -> None {
|
|
|
118
303
|
raise RuntimeError("No project root found") ;
|
|
119
304
|
}
|
|
120
305
|
|
|
121
|
-
_regenerate_and_install(config.project_root);
|
|
306
|
+
_regenerate_and_install(Path(str(config.project_root)));
|
|
122
307
|
}
|
|
123
308
|
|
|
124
309
|
"""Remove an npm package."""
|
|
@@ -129,7 +314,7 @@ def _npm_remove_handler(
|
|
|
129
314
|
raise RuntimeError("No project root found") ;
|
|
130
315
|
}
|
|
131
316
|
|
|
132
|
-
project_dir = config.project_root;
|
|
317
|
+
project_dir: Path = Path(str(config.project_root));
|
|
133
318
|
|
|
134
319
|
# Remove from config (core JacConfig handles this)
|
|
135
320
|
result = config.remove_dependency(package_name, dev=is_dev, dep_type="npm");
|
|
@@ -144,19 +329,25 @@ def _npm_remove_handler(
|
|
|
144
329
|
_regenerate_and_install(project_dir);
|
|
145
330
|
}
|
|
146
331
|
|
|
147
|
-
"""Regenerate package.json from jac.toml and run
|
|
332
|
+
"""Regenerate package.json from jac.toml and run bun install."""
|
|
148
333
|
def _regenerate_and_install(project_dir: Path) -> None {
|
|
149
334
|
import from jac_client.plugin.src.vite_bundler { ViteBundler }
|
|
335
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
150
336
|
import shutil;
|
|
151
337
|
|
|
338
|
+
# Ensure Bun is installed before proceeding (prompt to install if not)
|
|
339
|
+
if not ensure_bun_available() {
|
|
340
|
+
raise RuntimeError("Bun is required. Install manually: https://bun.sh") from None ;
|
|
341
|
+
}
|
|
342
|
+
|
|
152
343
|
bundler = ViteBundler(project_dir);
|
|
153
344
|
bundler.create_package_json();
|
|
154
345
|
|
|
155
|
-
# Install to .jac/client/ directory
|
|
346
|
+
# Install to .jac/client/ directory
|
|
156
347
|
client_dir = bundler._get_client_dir();
|
|
157
348
|
client_dir.mkdir(parents=True, exist_ok=True);
|
|
158
349
|
|
|
159
|
-
# Copy package.json to .jac/client/ for
|
|
350
|
+
# Copy package.json to .jac/client/ for bun install
|
|
160
351
|
configs_package_json = client_dir / 'configs' / 'package.json';
|
|
161
352
|
build_package_json = client_dir / 'package.json';
|
|
162
353
|
if configs_package_json.exists() {
|
|
@@ -164,32 +355,23 @@ def _regenerate_and_install(project_dir: Path) -> None {
|
|
|
164
355
|
}
|
|
165
356
|
|
|
166
357
|
try {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
cwd=client_dir,
|
|
170
|
-
check=True,
|
|
171
|
-
capture_output=True,
|
|
172
|
-
text=True
|
|
173
|
-
);
|
|
358
|
+
# Run bun install
|
|
359
|
+
subprocess.run(['bun', 'install'], cwd=client_dir, check=True, timeout=300);
|
|
174
360
|
} except subprocess.CalledProcessError as e {
|
|
175
|
-
raise RuntimeError(f"Failed to install
|
|
176
|
-
} except FileNotFoundError {
|
|
177
|
-
raise RuntimeError(
|
|
178
|
-
"npm command not found. Ensure Node.js and npm are installed."
|
|
179
|
-
) from None ;
|
|
361
|
+
raise RuntimeError(f"Failed to install packages: {e}") from e ;
|
|
180
362
|
} finally {
|
|
181
363
|
# Clean up temporary package.json
|
|
182
364
|
if build_package_json.exists() {
|
|
183
365
|
build_package_json.unlink();
|
|
184
366
|
}
|
|
185
|
-
# Move
|
|
186
|
-
|
|
187
|
-
if
|
|
188
|
-
|
|
189
|
-
if
|
|
190
|
-
|
|
367
|
+
# Move bun.lockb to configs/ if it exists
|
|
368
|
+
build_bun_lockb = client_dir / 'bun.lockb';
|
|
369
|
+
if build_bun_lockb.exists() {
|
|
370
|
+
configs_bun_lockb = client_dir / 'configs' / 'bun.lockb';
|
|
371
|
+
if configs_bun_lockb.exists() {
|
|
372
|
+
configs_bun_lockb.unlink();
|
|
191
373
|
}
|
|
192
|
-
|
|
374
|
+
build_bun_lockb.rename(configs_bun_lockb);
|
|
193
375
|
}
|
|
194
376
|
}
|
|
195
377
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Vite client bundle processing modules."""
|
|
2
2
|
import from jac_client.plugin.src.asset_processor { AssetProcessor }
|
|
3
|
-
import from jac_client.plugin.src.babel_processor { BabelProcessor }
|
|
4
3
|
import from jac_client.plugin.src.compiler { ViteCompiler }
|
|
5
4
|
import from jac_client.plugin.src.config_loader { JacClientConfig }
|
|
6
5
|
import from jac_client.plugin.src.import_processor { ImportProcessor }
|
|
@@ -10,7 +9,6 @@ import from jac_client.plugin.src.vite_bundler { ViteBundler }
|
|
|
10
9
|
|
|
11
10
|
glob __all__ = [
|
|
12
11
|
'AssetProcessor',
|
|
13
|
-
'BabelProcessor',
|
|
14
12
|
'ViteCompiler',
|
|
15
13
|
'JacClientConfig',
|
|
16
14
|
'ImportProcessor',
|
|
@@ -6,7 +6,6 @@ import from types { ModuleType }
|
|
|
6
6
|
import from typing { TYPE_CHECKING, Any }
|
|
7
7
|
import from jaclang.runtimelib.client_bundle { ClientBundleError }
|
|
8
8
|
import from .asset_processor { AssetProcessor }
|
|
9
|
-
import from .babel_processor { BabelProcessor }
|
|
10
9
|
import from .import_processor { ImportProcessor }
|
|
11
10
|
import from .jac_to_js { JacToJSCompiler }
|
|
12
11
|
import from .vite_bundler { ViteBundler }
|
|
@@ -21,6 +21,7 @@ class JacClientConfig(PluginConfigBase) {
|
|
|
21
21
|
def save(self: JacClientConfig) -> None;
|
|
22
22
|
def get_vite_config(self: JacClientConfig) -> dict[str, Any];
|
|
23
23
|
def get_ts_config(self: JacClientConfig) -> dict[str, Any];
|
|
24
|
+
def get_configs(self: JacClientConfig) -> dict[str, Any];
|
|
24
25
|
def get_package_config(self: JacClientConfig) -> dict[str, Any];
|
|
25
26
|
def add_dependency(
|
|
26
27
|
self: JacClientConfig, name: str, version: str, is_dev: bool = False
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Configuration loader for Desktop target (Tauri).
|
|
2
|
+
|
|
3
|
+
This module provides configuration access for the desktop target.
|
|
4
|
+
Configuration is loaded from jac.toml under [desktop] section.
|
|
5
|
+
|
|
6
|
+
Similar to JacClientConfig but loads [desktop] directly (not under [plugins]).
|
|
7
|
+
"""
|
|
8
|
+
import from pathlib { Path }
|
|
9
|
+
import from typing { Any }
|
|
10
|
+
import from jaclang.project.config { JacConfig, get_config }
|
|
11
|
+
|
|
12
|
+
"""Desktop target configuration loader.
|
|
13
|
+
|
|
14
|
+
Provides access to desktop/Tauri configuration
|
|
15
|
+
from the [desktop] section of jac.toml.
|
|
16
|
+
"""
|
|
17
|
+
class DesktopConfig {
|
|
18
|
+
has project_dir: Path | None = None,
|
|
19
|
+
_config: dict[str, Any] | None = None,
|
|
20
|
+
_jac_config: JacConfig | None = None;
|
|
21
|
+
|
|
22
|
+
def init(self: DesktopConfig, project_dir: Path | None = None) -> None;
|
|
23
|
+
def load(self: DesktopConfig) -> dict[str, Any];
|
|
24
|
+
def get_desktop_config(self: DesktopConfig) -> dict[str, Any];
|
|
25
|
+
def get_window_config(self: DesktopConfig) -> dict[str, Any];
|
|
26
|
+
def get_platforms_config(self: DesktopConfig) -> dict[str, Any];
|
|
27
|
+
def get_features_config(self: DesktopConfig) -> dict[str, Any];
|
|
28
|
+
def validate(self: DesktopConfig) -> None;
|
|
29
|
+
def get_default_config(self: DesktopConfig) -> dict[str, Any];
|
|
30
|
+
# def _get_jac_config(self: DesktopConfig) -> JacConfig;
|
|
31
|
+
}
|
|
@@ -16,7 +16,6 @@ impl ViteCompiler._get_client_dir(self: ViteCompiler) -> Path {
|
|
|
16
16
|
impl ViteCompiler.compile_and_bundle(
|
|
17
17
|
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
18
18
|
) -> tuple[str, str, list[str], list[str]] {
|
|
19
|
-
self.compile_runtime_utils();
|
|
20
19
|
(module_js, mod, module_manifest) = self.jac_compiler.compile_module(module_path);
|
|
21
20
|
collected_exports: set[str] = set(
|
|
22
21
|
self.jac_compiler.extract_exports(module_manifest)
|
|
@@ -28,14 +27,14 @@ impl ViteCompiler.compile_and_bundle(
|
|
|
28
27
|
collected_exports=collected_exports,
|
|
29
28
|
collected_globals=collected_globals
|
|
30
29
|
);
|
|
30
|
+
# Compile runtime AFTER dependencies so it overwrites any dependency-compiled
|
|
31
|
+
# version of client_runtime.js with the proper ES module exports
|
|
32
|
+
self.compile_runtime_utils();
|
|
31
33
|
self.copy_root_assets();
|
|
32
34
|
self.create_entry_file(module_path);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self.
|
|
36
|
-
self.compiled_dir, (client_dir / 'build'), self.asset_processor
|
|
37
|
-
);
|
|
38
|
-
entry_file = client_dir / 'build' / '_entry.js';
|
|
35
|
+
# Vite handles JSX/TSX transpilation natively with Bun - no Babel needed
|
|
36
|
+
# Vite builds directly from compiled/ directory
|
|
37
|
+
entry_file = self.compiled_dir / '_entry.js';
|
|
39
38
|
self.vite_bundler.build(entry_file=entry_file);
|
|
40
39
|
(bundle_code, bundle_hash) = self.vite_bundler.read_bundle();
|
|
41
40
|
client_exports = sorted(collected_exports);
|
|
@@ -49,7 +48,7 @@ impl ViteCompiler.create_entry_file(self: ViteCompiler, module_path: Path) -> No
|
|
|
49
48
|
entry_file = self.compiled_dir / '_entry.js';
|
|
50
49
|
# Derive the app module filename from the entry point (e.g., main.jac -> main.js, app.jac -> app.js)
|
|
51
50
|
app_module_name = module_path.stem;
|
|
52
|
-
entry_content = f'import React from "react";\nimport {{ createRoot }} from "react-dom/client";\nimport {{ app as App }} from "./{app_module_name}.js";\n\nconst root = createRoot(document.getElementById("root"));\nroot.render(
|
|
51
|
+
entry_content = f'import React from "react";\nimport {{ createRoot }} from "react-dom/client";\nimport {{ app as App }} from "./{app_module_name}.js";\nimport {{ JacClientErrorBoundary, ErrorFallback }} from "@jac/runtime";\n\nconst root = createRoot(document.getElementById("root"));\nroot.render(\n\tReact.createElement(\n\t\tJacClientErrorBoundary,{{ FallbackComponent: ErrorFallback }},\n\t\tReact.createElement(App, null)\n\t)\n);\n';
|
|
53
52
|
entry_file.write_text(entry_content, encoding='utf-8');
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -59,11 +58,10 @@ impl ViteCompiler.copy_root_assets(self: ViteCompiler) -> None {
|
|
|
59
58
|
compiled_assets_dir = self.compiled_dir / 'assets';
|
|
60
59
|
if (root_assets_dir.exists() and root_assets_dir.is_dir()) {
|
|
61
60
|
self.asset_processor.copy_assets(root_assets_dir, compiled_assets_dir);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
self.asset_processor.copy_custom_asset_types(root_assets_dir, build_assets_dir);
|
|
61
|
+
# Copy configured custom asset types to compiled/assets/
|
|
62
|
+
self.asset_processor.copy_custom_asset_types(
|
|
63
|
+
root_assets_dir, compiled_assets_dir
|
|
64
|
+
);
|
|
67
65
|
}
|
|
68
66
|
}
|
|
69
67
|
|
|
@@ -189,7 +187,21 @@ impl ViteCompiler.compile_dependencies_recursively(
|
|
|
189
187
|
output_path = self.compiled_dir / name;
|
|
190
188
|
}
|
|
191
189
|
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
192
|
-
|
|
190
|
+
# Add source file header comment for better error messages
|
|
191
|
+
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
|
+
output_path.write_text(source_header + combined_js, encoding='utf-8');
|
|
193
205
|
if (not manifest or not manifest.imports) {
|
|
194
206
|
return;
|
|
195
207
|
}
|
|
@@ -228,8 +240,29 @@ impl ViteCompiler.compile_runtime_utils(self: ViteCompiler) -> tuple[str, list[s
|
|
|
228
240
|
runtimeutils_exports_list = self.jac_compiler.extract_exports(
|
|
229
241
|
runtimeutils_manifest
|
|
230
242
|
);
|
|
231
|
-
|
|
232
|
-
|
|
243
|
+
# Include both function exports and glob exports (e.g., useState, useEffect)
|
|
244
|
+
glob_names = list(runtimeutils_manifest.globals) if runtimeutils_manifest else [];
|
|
245
|
+
all_exports = sorted(
|
|
246
|
+
set(runtimeutils_exports_list + self.ROUTER_EXPORTS + glob_names)
|
|
247
|
+
);
|
|
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;
|
|
233
266
|
self.compiled_dir.mkdir(parents=True, exist_ok=True);
|
|
234
267
|
(self.compiled_dir / 'client_runtime.js').write_text(
|
|
235
268
|
combined_runtime_utils_js, encoding='utf-8'
|
|
@@ -283,6 +316,5 @@ impl ViteCompiler.init(
|
|
|
283
316
|
);
|
|
284
317
|
self.import_processor = ImportProcessor();
|
|
285
318
|
self.asset_processor = AssetProcessor();
|
|
286
|
-
self.babel_processor = BabelProcessor(self.project_dir);
|
|
287
319
|
self.vite_bundler = ViteBundler(self.project_dir, vite_output_dir, vite_minify);
|
|
288
320
|
}
|
|
@@ -27,6 +27,7 @@ impl JacClientConfig.get_default_config(self: JacClientConfig) -> dict[str, Any]
|
|
|
27
27
|
'resolve': {}
|
|
28
28
|
},
|
|
29
29
|
'ts': {'compilerOptions': {}, 'include': [], 'exclude': []},
|
|
30
|
+
'configs': {}, # Generic config file generation: { "postcss": {...}, "tailwind": {...} }
|
|
30
31
|
'package': {
|
|
31
32
|
'name': '',
|
|
32
33
|
'version': '1.0.0',
|
|
@@ -61,6 +62,7 @@ impl JacClientConfig.load(self: JacClientConfig) -> dict[str, Any] {
|
|
|
61
62
|
user_config: dict[str, Any] = {
|
|
62
63
|
'vite': client_config.get('vite', {}),
|
|
63
64
|
'ts': client_config.get('ts', {}),
|
|
65
|
+
'configs': client_config.get('configs', {}),
|
|
64
66
|
'package': {
|
|
65
67
|
'name': jac_config.project.name,
|
|
66
68
|
'version': jac_config.project.version,
|
|
@@ -91,6 +93,12 @@ impl JacClientConfig.get_ts_config(self: JacClientConfig) -> dict[str, Any] {
|
|
|
91
93
|
return config.get('ts', {});
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
"""Get generic config files to generate (postcss, tailwind, etc.)."""
|
|
97
|
+
impl JacClientConfig.get_configs(self: JacClientConfig) -> dict[str, Any] {
|
|
98
|
+
config = self.load();
|
|
99
|
+
return config.get('configs', {});
|
|
100
|
+
}
|
|
101
|
+
|
|
94
102
|
"""Save configuration back to jac.toml using core JacConfig."""
|
|
95
103
|
impl JacClientConfig.save(self: JacClientConfig) -> None {
|
|
96
104
|
jac_config = self.get_jac_config();
|