jac-client 0.2.10__py3-none-any.whl → 0.2.12__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 +340 -371
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +19 -12
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +31 -15
- jac_client/examples/all-in-one/pages/LandingPage.jac +113 -90
- jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +34 -39
- jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +464 -352
- jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
- jac_client/examples/all-in-one/pages/nestedDemo.jac +43 -50
- jac_client/examples/all-in-one/pages/notFound.jac +14 -15
- 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 +77 -73
- jac_client/examples/asset-serving/image-asset/main.jac +47 -46
- jac_client/examples/asset-serving/import-alias/main.jac +93 -95
- jac_client/examples/basic/main.jac +17 -15
- jac_client/examples/basic-auth/main.jac +246 -254
- jac_client/examples/basic-auth-with-router/main.jac +272 -285
- jac_client/examples/basic-full-stack/main.jac +245 -242
- jac_client/examples/css-styling/js-styling/main.jac +41 -62
- jac_client/examples/css-styling/material-ui/main.jac +90 -90
- jac_client/examples/css-styling/pure-css/main.jac +35 -44
- jac_client/examples/css-styling/sass-example/main.jac +35 -44
- jac_client/examples/css-styling/styled-components/main.jac +38 -47
- jac_client/examples/css-styling/tailwind-example/main.jac +54 -43
- jac_client/examples/full-stack-with-auth/main.jac +407 -433
- jac_client/examples/little-x/main.jac +306 -344
- jac_client/examples/little-x/src/submit-button.jac +15 -14
- jac_client/examples/nested-folders/nested-advance/main.jac +18 -27
- 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/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 +26 -26
- jac_client/examples/with-router/main.jac +186 -223
- jac_client/plugin/client_runtime.cl.jac +5 -3
- jac_client/plugin/impl/client_runtime.impl.jac +1 -1
- jac_client/plugin/plugin_config.jac +53 -99
- jac_client/plugin/src/__init__.jac +0 -2
- jac_client/plugin/src/compiler.jac +0 -1
- jac_client/plugin/src/impl/compiler.impl.jac +49 -17
- 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 +146 -84
- jac_client/plugin/src/targets/impl/desktop_target.impl.jac +54 -41
- jac_client/plugin/utils/__init__.jac +3 -0
- jac_client/plugin/utils/bun_installer.jac +16 -0
- jac_client/plugin/utils/client_deps.jac +14 -0
- jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
- jac_client/plugin/utils/impl/client_deps.impl.jac +73 -0
- jac_client/templates/client.jacpack +0 -4
- jac_client/templates/fullstack.jacpack +1 -5
- jac_client/tests/conftest.py +56 -41
- 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 +71 -6
- jac_client/tests/test_helpers.py +11 -18
- jac_client/tests/test_it.py +1 -1
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/METADATA +5 -5
- jac_client-0.2.12.dist-info/RECORD +115 -0
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/WHEEL +1 -1
- jac_client/plugin/src/babel_processor.jac +0 -18
- jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
- jac_client/plugin/utils/impl/node_installer.impl.jac +0 -249
- jac_client/plugin/utils/node_installer.jac +0 -41
- jac_client-0.2.10.dist-info/RECORD +0 -115
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/entry_points.txt +0 -0
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/top_level.txt +0 -0
|
@@ -157,41 +157,26 @@ def _load_template(template_name: str) -> dict[str, Any] | None {
|
|
|
157
157
|
# ===============================================================================
|
|
158
158
|
# Post-create Hook for Client Template
|
|
159
159
|
# ===============================================================================
|
|
160
|
-
"""Post-create hook to ensure
|
|
160
|
+
"""Post-create hook to ensure Bun is installed and optionally install packages."""
|
|
161
161
|
def _post_create_client(project_path: Path, project_name: str) -> None {
|
|
162
162
|
import from jac_client.plugin.src.vite_bundler { ViteBundler }
|
|
163
|
-
import from jac_client.plugin.utils.node_installer { NodeInstaller }
|
|
164
163
|
import from jaclang.cli.console { console }
|
|
165
|
-
import
|
|
164
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
166
165
|
|
|
167
|
-
# First, ensure
|
|
166
|
+
# First, ensure Bun is installed (prompt to install if not)
|
|
168
167
|
console.print();
|
|
169
|
-
|
|
170
|
-
"
|
|
171
|
-
|
|
172
|
-
node_result = NodeInstaller.ensure_node_installed(interactive=True);
|
|
173
|
-
node_installed = node_result[0];
|
|
174
|
-
message = node_result[1];
|
|
175
|
-
was_just_installed = node_result[2];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if not node_installed {
|
|
179
|
-
console.warning(f"Node.js is required for client development");
|
|
180
|
-
console.print(f"\n {message}", file=sys.stderr);
|
|
181
|
-
console.print(
|
|
182
|
-
" After installing Node.js, run: jac add --cl\n",
|
|
183
|
-
style="muted",
|
|
184
|
-
file=sys.stderr
|
|
185
|
-
);
|
|
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");
|
|
186
171
|
return;
|
|
187
172
|
}
|
|
188
173
|
|
|
189
|
-
console.print(
|
|
174
|
+
console.print(" ✔ Bun is installed", style="success");
|
|
190
175
|
|
|
191
|
-
# Check if
|
|
176
|
+
# Check if package installation should be skipped
|
|
192
177
|
if os.environ.get("JAC_CLIENT_SKIP_NPM_INSTALL") {
|
|
193
178
|
console.print(
|
|
194
|
-
"\n ⏭ Skipping
|
|
179
|
+
"\n ⏭ Skipping package installation (JAC_CLIENT_SKIP_NPM_INSTALL is set)",
|
|
195
180
|
style="muted"
|
|
196
181
|
);
|
|
197
182
|
console.print(
|
|
@@ -223,7 +208,7 @@ def _post_create_client(project_path: Path, project_name: str) -> None {
|
|
|
223
208
|
client_dir = bundler._get_client_dir();
|
|
224
209
|
client_dir.mkdir(parents=True, exist_ok=True);
|
|
225
210
|
|
|
226
|
-
# Copy package.json to .jac/client/ for
|
|
211
|
+
# Copy package.json to .jac/client/ for bun install
|
|
227
212
|
configs_package_json = client_dir / 'configs' / 'package.json';
|
|
228
213
|
build_package_json = client_dir / 'package.json';
|
|
229
214
|
|
|
@@ -237,38 +222,38 @@ def _post_create_client(project_path: Path, project_name: str) -> None {
|
|
|
237
222
|
|
|
238
223
|
shutil.copy2(configs_package_json, build_package_json);
|
|
239
224
|
|
|
240
|
-
# Run
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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();
|
|
249
236
|
}
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
250
239
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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();
|
|
257
250
|
}
|
|
258
|
-
shutil.move(str(
|
|
251
|
+
shutil.move(str(build_bun_lockb), str(configs_bun_lockb));
|
|
259
252
|
}
|
|
260
253
|
|
|
261
|
-
console.print(" ✔
|
|
254
|
+
console.print(" ✔ Packages installed", style="success");
|
|
262
255
|
} except subprocess.CalledProcessError as e {
|
|
263
|
-
console.warning(f"Failed to install packages: {e
|
|
264
|
-
console.print(
|
|
265
|
-
" 💡 You can install packages later with: jac add --cl\n",
|
|
266
|
-
style="muted"
|
|
267
|
-
);
|
|
268
|
-
} except FileNotFoundError {
|
|
269
|
-
console.warning(
|
|
270
|
-
"npm command not found. This may require reloading your shell."
|
|
271
|
-
);
|
|
256
|
+
console.warning(f"Failed to install packages: {e}");
|
|
272
257
|
console.print(
|
|
273
258
|
" 💡 You can install packages later with: jac add --cl\n",
|
|
274
259
|
style="muted"
|
|
@@ -285,19 +270,6 @@ def _post_create_client(project_path: Path, project_name: str) -> None {
|
|
|
285
270
|
" 💡 You can install packages later with: jac add --cl\n", style="muted"
|
|
286
271
|
);
|
|
287
272
|
}
|
|
288
|
-
|
|
289
|
-
# If Node.js was just installed, offer to restart terminal for full integration
|
|
290
|
-
if was_just_installed {
|
|
291
|
-
console.print();
|
|
292
|
-
console.info("Node.js was just installed via NVM");
|
|
293
|
-
console.print(
|
|
294
|
-
"\n For Node.js to be available in your current shell:", style="muted"
|
|
295
|
-
);
|
|
296
|
-
console.print(" 1. Run: source ~/.nvm/nvm.sh", style="muted");
|
|
297
|
-
console.print(" 2. Or restart your terminal", style="muted");
|
|
298
|
-
console.print("\n 💡 npm commands from jac work immediately", style="info");
|
|
299
|
-
console.print();
|
|
300
|
-
}
|
|
301
273
|
}
|
|
302
274
|
|
|
303
275
|
# ===============================================================================
|
|
@@ -357,39 +329,25 @@ def _npm_remove_handler(
|
|
|
357
329
|
_regenerate_and_install(project_dir);
|
|
358
330
|
}
|
|
359
331
|
|
|
360
|
-
"""Regenerate package.json from jac.toml and run
|
|
332
|
+
"""Regenerate package.json from jac.toml and run bun install."""
|
|
361
333
|
def _regenerate_and_install(project_dir: Path) -> None {
|
|
362
334
|
import from jac_client.plugin.src.vite_bundler { ViteBundler }
|
|
363
|
-
import from jac_client.plugin.utils
|
|
335
|
+
import from jac_client.plugin.utils { ensure_bun_available }
|
|
364
336
|
import shutil;
|
|
365
337
|
|
|
366
|
-
# Ensure
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
message = node_result[1];
|
|
370
|
-
was_just_installed = node_result[2];
|
|
371
|
-
|
|
372
|
-
if not node_installed {
|
|
373
|
-
raise RuntimeError(
|
|
374
|
-
f"Node.js installation required:\n{message}\n" + "Please install Node.js and try again."
|
|
375
|
-
) ;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
# Inform user if Node.js was just installed
|
|
379
|
-
if was_just_installed {
|
|
380
|
-
print(
|
|
381
|
-
"\nNote: Node.js was just installed. npm commands will work via NVM sourcing."
|
|
382
|
-
);
|
|
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 ;
|
|
383
341
|
}
|
|
384
342
|
|
|
385
343
|
bundler = ViteBundler(project_dir);
|
|
386
344
|
bundler.create_package_json();
|
|
387
345
|
|
|
388
|
-
# Install to .jac/client/ directory
|
|
346
|
+
# Install to .jac/client/ directory
|
|
389
347
|
client_dir = bundler._get_client_dir();
|
|
390
348
|
client_dir.mkdir(parents=True, exist_ok=True);
|
|
391
349
|
|
|
392
|
-
# Copy package.json to .jac/client/ for
|
|
350
|
+
# Copy package.json to .jac/client/ for bun install
|
|
393
351
|
configs_package_json = client_dir / 'configs' / 'package.json';
|
|
394
352
|
build_package_json = client_dir / 'package.json';
|
|
395
353
|
if configs_package_json.exists() {
|
|
@@ -397,27 +355,23 @@ def _regenerate_and_install(project_dir: Path) -> None {
|
|
|
397
355
|
}
|
|
398
356
|
|
|
399
357
|
try {
|
|
400
|
-
#
|
|
401
|
-
|
|
358
|
+
# Run bun install
|
|
359
|
+
subprocess.run(['bun', 'install'], cwd=client_dir, check=True, timeout=300);
|
|
402
360
|
} except subprocess.CalledProcessError as e {
|
|
403
|
-
raise RuntimeError(f"Failed to install
|
|
404
|
-
} except FileNotFoundError {
|
|
405
|
-
raise RuntimeError(
|
|
406
|
-
"npm command not found. This may require reloading your shell after Node.js installation."
|
|
407
|
-
) from None ;
|
|
361
|
+
raise RuntimeError(f"Failed to install packages: {e}") from e ;
|
|
408
362
|
} finally {
|
|
409
363
|
# Clean up temporary package.json
|
|
410
364
|
if build_package_json.exists() {
|
|
411
365
|
build_package_json.unlink();
|
|
412
366
|
}
|
|
413
|
-
# Move
|
|
414
|
-
|
|
415
|
-
if
|
|
416
|
-
|
|
417
|
-
if
|
|
418
|
-
|
|
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();
|
|
419
373
|
}
|
|
420
|
-
|
|
374
|
+
build_bun_lockb.rename(configs_bun_lockb);
|
|
421
375
|
}
|
|
422
376
|
}
|
|
423
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 }
|
|
@@ -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";\nimport {{ JacClientErrorBoundary, ErrorFallback }} from "@jac
|
|
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
|
}
|
|
@@ -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);
|