jac-client 0.2.2__py3-none-any.whl → 0.2.6__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/assets/workers/worker.py +5 -0
- jac_client/examples/all-in-one/src/app.jac +841 -0
- jac_client/examples/all-in-one/{button.jac → src/button.jac} +1 -1
- jac_client/examples/all-in-one/{components → src/components}/button.jac +1 -1
- jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +2 -2
- jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +2 -2
- jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +7 -7
- jac_client/examples/basic/{app.jac → src/app.jac} +2 -2
- jac_client/examples/basic-auth/src/app.jac +377 -0
- jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +18 -18
- jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +175 -130
- jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +5 -5
- jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +5 -5
- jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +6 -6
- jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +37 -37
- jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
- jac_client/examples/little-x/src/submit-button.jac +16 -0
- jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
- jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
- jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
- jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
- jac_client/examples/ts-support/src/app.jac +35 -0
- jac_client/examples/with-router/{app.jac → src/app.jac} +11 -11
- jac_client/plugin/cli.jac +547 -0
- jac_client/plugin/client.jac +52 -0
- jac_client/plugin/client_runtime.cl.jac +38 -0
- jac_client/plugin/impl/client.impl.jac +134 -0
- jac_client/plugin/impl/client_runtime.impl.jac +177 -0
- jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
- jac_client/plugin/plugin_config.jac +195 -0
- jac_client/plugin/src/__init__.jac +20 -0
- jac_client/plugin/src/asset_processor.jac +33 -0
- jac_client/plugin/src/babel_processor.jac +18 -0
- jac_client/plugin/src/compiler.jac +66 -0
- jac_client/plugin/src/config_loader.jac +32 -0
- jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
- jac_client/plugin/src/impl/babel_processor.impl.jac +84 -0
- jac_client/plugin/src/impl/compiler.impl.jac +251 -0
- jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
- jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
- jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
- jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
- jac_client/plugin/src/impl/vite_bundler.impl.jac +513 -0
- jac_client/plugin/src/import_processor.jac +19 -0
- jac_client/plugin/src/jac_to_js.jac +35 -0
- jac_client/plugin/src/package_installer.jac +26 -0
- jac_client/plugin/src/vite_bundler.jac +36 -0
- jac_client/plugin/vite_client_bundle.jac +31 -0
- jac_client/tests/conftest.py +281 -0
- jac_client/tests/fixtures/basic-app/app.jac +2 -2
- jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
- jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
- jac_client/tests/fixtures/js_import/app.jac +5 -5
- jac_client/tests/fixtures/spawn_test/app.jac +7 -7
- jac_client/tests/fixtures/with-ts/app.jac +35 -0
- jac_client/tests/test_cli.py +755 -0
- jac_client/tests/test_it.py +347 -67
- {jac_client-0.2.2.dist-info → jac_client-0.2.6.dist-info}/METADATA +30 -24
- jac_client-0.2.6.dist-info/RECORD +74 -0
- {jac_client-0.2.2.dist-info → jac_client-0.2.6.dist-info}/WHEEL +2 -1
- jac_client-0.2.6.dist-info/entry_points.txt +4 -0
- jac_client-0.2.6.dist-info/top_level.txt +1 -0
- jac_client/docs/README.md +0 -689
- jac_client/docs/advanced-state.md +0 -1265
- jac_client/docs/asset-serving/intro.md +0 -209
- jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/app.jac.md +0 -121
- jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client/docs/file-system/intro.md +0 -72
- jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client/docs/guide-example/intro.md +0 -115
- jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client/docs/imports.md +0 -1141
- jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client/docs/routing.md +0 -659
- jac_client/docs/styling/intro.md +0 -249
- jac_client/docs/styling/js-styling.md +0 -367
- jac_client/docs/styling/material-ui.md +0 -341
- jac_client/docs/styling/pure-css.md +0 -299
- jac_client/docs/styling/sass.md +0 -403
- jac_client/docs/styling/styled-components.md +0 -395
- jac_client/docs/styling/tailwind.md +0 -298
- jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client/examples/all-in-one/README.md +0 -16
- jac_client/examples/all-in-one/app.jac +0 -426
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/package.json +0 -29
- jac_client/examples/all-in-one/styles.css +0 -26
- jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client/examples/basic/.babelrc +0 -9
- jac_client/examples/basic/README.md +0 -16
- jac_client/examples/basic/package.json +0 -27
- jac_client/examples/basic/vite.config.js +0 -27
- jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client/examples/basic-auth/README.md +0 -16
- jac_client/examples/basic-auth/app.jac +0 -308
- jac_client/examples/basic-auth/package.json +0 -27
- jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client/examples/little-x/package.json +0 -23
- jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client/examples/with-router/.babelrc +0 -9
- jac_client/examples/with-router/README.md +0 -17
- jac_client/examples/with-router/package.json +0 -28
- jac_client/examples/with-router/vite.config.js +0 -27
- jac_client/plugin/cli.py +0 -244
- jac_client/plugin/client.py +0 -152
- jac_client/plugin/client_runtime.jac +0 -234
- jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client/tests/fixtures/package.json +0 -11
- jac_client/tests/test_asset_examples.py +0 -322
- jac_client/tests/test_cl.py +0 -530
- jac_client/tests/test_create_jac_app.py +0 -131
- jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.2.dist-info/RECORD +0 -171
- jac_client-0.2.2.dist-info/entry_points.txt +0 -4
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Main compilation orchestration module."""
|
|
2
|
+
import contextlib;
|
|
3
|
+
import from collections.abc { Callable }
|
|
4
|
+
import from pathlib { Path }
|
|
5
|
+
import from types { ModuleType }
|
|
6
|
+
import from typing { TYPE_CHECKING, Any }
|
|
7
|
+
import from jaclang.runtimelib.client_bundle { ClientBundleError }
|
|
8
|
+
import from .asset_processor { AssetProcessor }
|
|
9
|
+
import from .babel_processor { BabelProcessor }
|
|
10
|
+
import from .import_processor { ImportProcessor }
|
|
11
|
+
import from .jac_to_js { JacToJSCompiler }
|
|
12
|
+
import from .vite_bundler { ViteBundler }
|
|
13
|
+
|
|
14
|
+
with entry {
|
|
15
|
+
if TYPE_CHECKING { }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
"""Orchestrates the compilation process for Vite client bundles."""
|
|
19
|
+
class ViteCompiler {
|
|
20
|
+
with entry {
|
|
21
|
+
ROUTER_EXPORTS = [
|
|
22
|
+
'Router',
|
|
23
|
+
'Routes',
|
|
24
|
+
'Route',
|
|
25
|
+
'Link',
|
|
26
|
+
'Navigate',
|
|
27
|
+
'useNavigate',
|
|
28
|
+
'useLocation',
|
|
29
|
+
'useParams'
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def init(
|
|
34
|
+
self: ViteCompiler,
|
|
35
|
+
vite_package_json: Path,
|
|
36
|
+
vite_output_dir: (Path | None) = None,
|
|
37
|
+
vite_minify: bool = False,
|
|
38
|
+
runtime_path: (Path | None) = None,
|
|
39
|
+
compile_to_js_func:
|
|
40
|
+
(Callable[([Path], tuple[(str, (ModuleType | None))])] | None) = None,
|
|
41
|
+
extract_exports_func: (Callable[([Any], list[str])] | None) = None,
|
|
42
|
+
extract_globals_func: (Callable[([Any, ModuleType], dict[(str, Any)])] | None) = None
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
def compile_runtime_utils(self: ViteCompiler) -> tuple[str, list[str]];
|
|
46
|
+
def compile_dependencies_recursively(
|
|
47
|
+
self: ViteCompiler,
|
|
48
|
+
module_path: Path,
|
|
49
|
+
visited: (set[Path] | None) = None,
|
|
50
|
+
collected_exports: (set[str] | None) = None,
|
|
51
|
+
collected_globals: (dict[(str, Any)] | None) = None,
|
|
52
|
+
source_root: (Path | None) = None
|
|
53
|
+
) -> None;
|
|
54
|
+
|
|
55
|
+
def _copy_js_file(self: ViteCompiler, js_path: Path, source_root: Path) -> None;
|
|
56
|
+
def _copy_ts_file(self: ViteCompiler, ts_path: Path, source_root: Path) -> None;
|
|
57
|
+
def _copy_asset_file(
|
|
58
|
+
self: ViteCompiler, asset_path: Path, source_root: Path
|
|
59
|
+
) -> None;
|
|
60
|
+
|
|
61
|
+
def copy_root_assets(self: ViteCompiler) -> None;
|
|
62
|
+
def create_entry_file(self: ViteCompiler) -> None;
|
|
63
|
+
def compile_and_bundle(
|
|
64
|
+
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
65
|
+
) -> tuple[str, str, list[str], list[str]];
|
|
66
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Configuration loader for Jac Client build system.
|
|
2
|
+
|
|
3
|
+
This module provides configuration access for the client plugin.
|
|
4
|
+
Configuration is loaded from jac.toml under [plugins.client] section.
|
|
5
|
+
|
|
6
|
+
Inherits from PluginConfigBase to eliminate boilerplate code.
|
|
7
|
+
"""
|
|
8
|
+
import from pathlib { Path }
|
|
9
|
+
import from typing { Any }
|
|
10
|
+
import from jaclang.project.plugin_config { PluginConfigBase }
|
|
11
|
+
|
|
12
|
+
"""Client-specific configuration loader.
|
|
13
|
+
|
|
14
|
+
Provides access to vite, ts, and package configuration
|
|
15
|
+
from the [plugins.client] section of jac.toml.
|
|
16
|
+
"""
|
|
17
|
+
class JacClientConfig(PluginConfigBase) {
|
|
18
|
+
override def get_plugin_name(self: JacClientConfig) -> str;
|
|
19
|
+
override def get_default_config(self: JacClientConfig) -> dict[str, Any];
|
|
20
|
+
override def load(self: JacClientConfig) -> dict[str, Any];
|
|
21
|
+
def save(self: JacClientConfig) -> None;
|
|
22
|
+
def get_vite_config(self: JacClientConfig) -> dict[str, Any];
|
|
23
|
+
def get_ts_config(self: JacClientConfig) -> dict[str, Any];
|
|
24
|
+
def get_package_config(self: JacClientConfig) -> dict[str, Any];
|
|
25
|
+
def add_dependency(
|
|
26
|
+
self: JacClientConfig, name: str, version: str, is_dev: bool = False
|
|
27
|
+
) -> None;
|
|
28
|
+
|
|
29
|
+
def remove_dependency(
|
|
30
|
+
self: JacClientConfig, name: str, is_dev: bool = False
|
|
31
|
+
) -> bool;
|
|
32
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Copy custom asset files (based on jac.toml configuration) from source to destination recursively."""
|
|
2
|
+
|
|
3
|
+
impl AssetProcessor.copy_custom_asset_types(
|
|
4
|
+
self: AssetProcessor,
|
|
5
|
+
src_dir: Path,
|
|
6
|
+
dest_dir: Path,
|
|
7
|
+
preserve_structure: bool = True
|
|
8
|
+
) -> None {
|
|
9
|
+
if not src_dir.exists() {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
dest_dir.mkdir(parents=True, exist_ok=True);
|
|
13
|
+
def copy_recursive(
|
|
14
|
+
source: Path, destination: Path, base: (Path | None) = None
|
|
15
|
+
) -> None {
|
|
16
|
+
if not source.exists() {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (base is None) {
|
|
20
|
+
base = source;
|
|
21
|
+
}
|
|
22
|
+
for item in source.iterdir() {
|
|
23
|
+
if (item.is_file() and (item.suffix.lower() in custom_asset_extensions)) {
|
|
24
|
+
if preserve_structure {
|
|
25
|
+
relative_path = item.relative_to(base);
|
|
26
|
+
dest_file = destination / relative_path;
|
|
27
|
+
} else {
|
|
28
|
+
dest_file = destination / item.name;
|
|
29
|
+
}
|
|
30
|
+
dest_file.parent.mkdir(parents=True, exist_ok=True);
|
|
31
|
+
with contextlib.suppress(OSError, shutil.Error) {
|
|
32
|
+
shutil.copy2(item, dest_file);
|
|
33
|
+
}
|
|
34
|
+
} elif item.is_dir() {
|
|
35
|
+
copy_recursive(item, destination, base);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
config = get_config();
|
|
40
|
+
assets_config = config.get_plugin_config("client").get("assets", {});
|
|
41
|
+
custom_asset_extensions = set(assets_config.get("custom_extensions", []));
|
|
42
|
+
if custom_asset_extensions {
|
|
43
|
+
copy_recursive(src_dir, dest_dir);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
"""Copy TypeScript files (.ts, .tsx) from source to destination recursively."""
|
|
49
|
+
impl AssetProcessor.copy_typescript_files(
|
|
50
|
+
self: AssetProcessor,
|
|
51
|
+
src_dir: Path,
|
|
52
|
+
dest_dir: Path,
|
|
53
|
+
preserve_structure: bool = True
|
|
54
|
+
) -> None {
|
|
55
|
+
if not src_dir.exists() {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
dest_dir.mkdir(parents=True, exist_ok=True);
|
|
59
|
+
ts_extensions = {'.ts','.tsx'};
|
|
60
|
+
def copy_recursive(
|
|
61
|
+
source: Path, destination: Path, base: (Path | None) = None
|
|
62
|
+
) -> None {
|
|
63
|
+
if not source.exists() {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (base is None) {
|
|
67
|
+
base = source;
|
|
68
|
+
}
|
|
69
|
+
for item in source.iterdir() {
|
|
70
|
+
if (item.is_file() and (item.suffix.lower() in ts_extensions)) {
|
|
71
|
+
if preserve_structure {
|
|
72
|
+
relative_path = item.relative_to(base);
|
|
73
|
+
dest_file = destination / relative_path;
|
|
74
|
+
} else {
|
|
75
|
+
dest_file = destination / item.name;
|
|
76
|
+
}
|
|
77
|
+
dest_file.parent.mkdir(parents=True, exist_ok=True);
|
|
78
|
+
with contextlib.suppress(OSError, shutil.Error) {
|
|
79
|
+
shutil.copy2(item, dest_file);
|
|
80
|
+
}
|
|
81
|
+
} elif item.is_dir() {
|
|
82
|
+
copy_recursive(item, destination, base);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
copy_recursive(src_dir, dest_dir);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
"""Copy CSS and other asset files from source to destination recursively."""
|
|
90
|
+
impl AssetProcessor.copy_assets(
|
|
91
|
+
self: AssetProcessor,
|
|
92
|
+
src_dir: Path,
|
|
93
|
+
dest_dir: Path,
|
|
94
|
+
preserve_structure: bool = True
|
|
95
|
+
) -> None {
|
|
96
|
+
if not src_dir.exists() {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
dest_dir.mkdir(parents=True, exist_ok=True);
|
|
100
|
+
def copy_recursive(
|
|
101
|
+
source: Path, destination: Path, base: (Path | None) = None
|
|
102
|
+
) -> None {
|
|
103
|
+
if not source.exists() {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (base is None) {
|
|
107
|
+
base = source;
|
|
108
|
+
}
|
|
109
|
+
for item in source.iterdir() {
|
|
110
|
+
if (item.is_file() and (item.suffix.lower() in self.ASSET_EXTENSIONS)) {
|
|
111
|
+
if preserve_structure {
|
|
112
|
+
relative_path = item.relative_to(base);
|
|
113
|
+
dest_file = destination / relative_path;
|
|
114
|
+
} else {
|
|
115
|
+
dest_file = destination / item.name;
|
|
116
|
+
}
|
|
117
|
+
dest_file.parent.mkdir(parents=True, exist_ok=True);
|
|
118
|
+
with contextlib.suppress(OSError, shutil.Error) {
|
|
119
|
+
shutil.copy2(item, dest_file);
|
|
120
|
+
}
|
|
121
|
+
} elif item.is_dir() {
|
|
122
|
+
copy_recursive(item, destination, base);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
copy_recursive(src_dir, dest_dir);
|
|
127
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Copy CSS, assets, and TypeScript files from compiled/ to build/ after Babel compilation."""
|
|
2
|
+
|
|
3
|
+
impl BabelProcessor.copy_assets_after_compile(
|
|
4
|
+
self: BabelProcessor,
|
|
5
|
+
compiled_dir: Path,
|
|
6
|
+
build_dir: Path,
|
|
7
|
+
asset_processor: AssetProcessor
|
|
8
|
+
) -> None {
|
|
9
|
+
asset_processor.copy_assets(compiled_dir, build_dir);
|
|
10
|
+
asset_processor.copy_typescript_files(compiled_dir, build_dir);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
"""Run Babel compilation (npm run compile)."""
|
|
14
|
+
impl BabelProcessor.compile(self: BabelProcessor) -> None {
|
|
15
|
+
bundler = ViteBundler(self.project_dir);
|
|
16
|
+
# Ensure root package.json exists temporarily for npm commands
|
|
17
|
+
bundler._ensure_root_package_json();
|
|
18
|
+
try {
|
|
19
|
+
# Ensure dependencies are installed (check if node_modules exists)
|
|
20
|
+
build_dir = self.project_dir / '.client-build';
|
|
21
|
+
node_modules = build_dir / 'node_modules';
|
|
22
|
+
if not node_modules.exists() {
|
|
23
|
+
# Temporarily copy package.json to .client-build/ for npm install
|
|
24
|
+
build_package_json = build_dir / 'package.json';
|
|
25
|
+
configs_package_json = build_dir / '.jac-client.configs' / 'package.json';
|
|
26
|
+
if configs_package_json.exists() and not build_package_json.exists() {
|
|
27
|
+
import shutil;
|
|
28
|
+
shutil.copy2(configs_package_json, build_package_json);
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
# Install to .client-build/node_modules
|
|
32
|
+
subprocess.run(
|
|
33
|
+
['npm', 'install'],
|
|
34
|
+
cwd=build_dir,
|
|
35
|
+
check=True,
|
|
36
|
+
capture_output=True,
|
|
37
|
+
text=True
|
|
38
|
+
);
|
|
39
|
+
} except subprocess.CalledProcessError as e {
|
|
40
|
+
raise ClientBundleError(
|
|
41
|
+
f'Failed to install npm dependencies: {e.stderr}'
|
|
42
|
+
) from e ;
|
|
43
|
+
} except FileNotFoundError {
|
|
44
|
+
raise ClientBundleError(
|
|
45
|
+
'npm command not found. Ensure Node.js and npm are installed.'
|
|
46
|
+
) from None ;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Temporarily copy package.json to .client-build/ for npm run compile
|
|
51
|
+
build_package_json = build_dir / 'package.json';
|
|
52
|
+
configs_package_json = build_dir / '.jac-client.configs' / 'package.json';
|
|
53
|
+
if configs_package_json.exists() and not build_package_json.exists() {
|
|
54
|
+
import shutil;
|
|
55
|
+
shutil.copy2(configs_package_json, build_package_json);
|
|
56
|
+
}
|
|
57
|
+
command = ['npm', 'run', 'compile'];
|
|
58
|
+
subprocess.run(
|
|
59
|
+
command, cwd=build_dir, check=True, capture_output=True, text=True
|
|
60
|
+
);
|
|
61
|
+
} finally {
|
|
62
|
+
# Clean up temporary package.json in .client-build/
|
|
63
|
+
build_package_json = build_dir / 'package.json';
|
|
64
|
+
if build_package_json.exists() {
|
|
65
|
+
build_package_json.unlink();
|
|
66
|
+
}
|
|
67
|
+
# Move package-lock.json to .jac-client.configs/ if it exists
|
|
68
|
+
build_package_lock = build_dir / 'package-lock.json';
|
|
69
|
+
if build_package_lock.exists() {
|
|
70
|
+
configs_package_lock = build_dir / '.jac-client.configs' / 'package-lock.json';
|
|
71
|
+
if configs_package_lock.exists() {
|
|
72
|
+
configs_package_lock.unlink();
|
|
73
|
+
}
|
|
74
|
+
build_package_lock.rename(configs_package_lock);
|
|
75
|
+
}
|
|
76
|
+
# Always clean up root package.json and move package-lock.json
|
|
77
|
+
bundler._cleanup_root_package_files();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
"""Initialize the Babel processor."""
|
|
82
|
+
impl BabelProcessor.init(self: BabelProcessor, project_dir: Path) {
|
|
83
|
+
self.project_dir = project_dir;
|
|
84
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""Compile module and dependencies, then bundle with Vite."""
|
|
2
|
+
|
|
3
|
+
impl ViteCompiler.compile_and_bundle(
|
|
4
|
+
self: ViteCompiler, module: ModuleType, module_path: Path
|
|
5
|
+
) -> tuple[str, str, list[str], list[str]] {
|
|
6
|
+
self.compile_runtime_utils();
|
|
7
|
+
(module_js, mod, module_manifest) = self.jac_compiler.compile_module(module_path);
|
|
8
|
+
collected_exports: set[str] = set(
|
|
9
|
+
self.jac_compiler.extract_exports(module_manifest)
|
|
10
|
+
);
|
|
11
|
+
client_globals_map = self.jac_compiler.extract_globals(module_manifest, module);
|
|
12
|
+
collected_globals: dict[(str, Any)] = dict(client_globals_map);
|
|
13
|
+
self.compile_dependencies_recursively(
|
|
14
|
+
module_path,
|
|
15
|
+
collected_exports=collected_exports,
|
|
16
|
+
collected_globals=collected_globals
|
|
17
|
+
);
|
|
18
|
+
self.copy_root_assets();
|
|
19
|
+
self.create_entry_file();
|
|
20
|
+
self.babel_processor.compile();
|
|
21
|
+
self.babel_processor.copy_assets_after_compile(
|
|
22
|
+
self.compiled_dir,
|
|
23
|
+
(self.project_dir / '.client-build' / 'build'),
|
|
24
|
+
self.asset_processor
|
|
25
|
+
);
|
|
26
|
+
entry_file = self.project_dir / '.client-build' / 'build' / 'main.js';
|
|
27
|
+
self.vite_bundler.build(entry_file=entry_file);
|
|
28
|
+
(bundle_code, bundle_hash) = self.vite_bundler.read_bundle();
|
|
29
|
+
client_exports = sorted(collected_exports);
|
|
30
|
+
client_globals = list(collected_globals.keys());
|
|
31
|
+
return (bundle_code, bundle_hash, client_exports, client_globals);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
"""Create the main entry file for Vite bundling."""
|
|
35
|
+
impl ViteCompiler.create_entry_file(self: ViteCompiler) -> None {
|
|
36
|
+
entry_file = self.compiled_dir / 'main.js';
|
|
37
|
+
entry_content = 'import React from "react";\nimport { createRoot } from "react-dom/client";\nimport { app as App } from "./app.js";\n\nconst root = createRoot(document.getElementById("root"));\nroot.render(<App />);\n';
|
|
38
|
+
entry_file.write_text(entry_content, encoding='utf-8');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
"""Copy assets from root assets/ folder to compiled/assets/ for @jac-client/assets alias."""
|
|
42
|
+
impl ViteCompiler.copy_root_assets(self: ViteCompiler) -> None {
|
|
43
|
+
root_assets_dir = self.project_dir / 'assets';
|
|
44
|
+
compiled_assets_dir = self.compiled_dir / 'assets';
|
|
45
|
+
if (root_assets_dir.exists() and root_assets_dir.is_dir()) {
|
|
46
|
+
self.asset_processor.copy_assets(root_assets_dir, compiled_assets_dir);
|
|
47
|
+
}
|
|
48
|
+
# Copy configured_asset files from root assets/ to build assets/ (bypassing compiled)
|
|
49
|
+
build_assets_dir = self.project_dir / '.client-build' / 'build' / 'assets';
|
|
50
|
+
if (root_assets_dir.exists() and root_assets_dir.is_dir()) {
|
|
51
|
+
self.asset_processor.copy_custom_asset_types(root_assets_dir, build_assets_dir);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
"""Copy an asset file to the compiled directory."""
|
|
56
|
+
impl ViteCompiler._copy_asset_file(
|
|
57
|
+
self: ViteCompiler, asset_path: Path, source_root: Path
|
|
58
|
+
) -> None {
|
|
59
|
+
if not asset_path.exists() {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
relative_path = asset_path.relative_to(source_root);
|
|
64
|
+
output_path = self.compiled_dir / relative_path;
|
|
65
|
+
} except ValueError {
|
|
66
|
+
output_path = self.compiled_dir / asset_path.name;
|
|
67
|
+
}
|
|
68
|
+
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
69
|
+
with contextlib.suppress(FileNotFoundError, OSError) {
|
|
70
|
+
output_path.write_text(
|
|
71
|
+
asset_path.read_text(encoding='utf-8'), encoding='utf-8'
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
"""Copy a TypeScript file to the compiled directory."""
|
|
77
|
+
impl ViteCompiler._copy_ts_file(
|
|
78
|
+
self: ViteCompiler, ts_path: Path, source_root: Path
|
|
79
|
+
) -> None {
|
|
80
|
+
if not ts_path.exists() {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
ts_code = ts_path.read_text(encoding='utf-8');
|
|
85
|
+
try {
|
|
86
|
+
relative_path = ts_path.relative_to(source_root);
|
|
87
|
+
output_path = self.compiled_dir / relative_path;
|
|
88
|
+
} except ValueError {
|
|
89
|
+
output_path = self.compiled_dir / ts_path.name;
|
|
90
|
+
}
|
|
91
|
+
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
92
|
+
output_path.write_text(ts_code, encoding='utf-8');
|
|
93
|
+
} except (FileNotFoundError, OSError) { }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
"""Copy a JavaScript file to the compiled directory."""
|
|
97
|
+
impl ViteCompiler._copy_js_file(
|
|
98
|
+
self: ViteCompiler, js_path: Path, source_root: Path
|
|
99
|
+
) -> None {
|
|
100
|
+
try {
|
|
101
|
+
js_code = js_path.read_text(encoding='utf-8');
|
|
102
|
+
try {
|
|
103
|
+
relative_path = js_path.relative_to(source_root);
|
|
104
|
+
output_path = self.compiled_dir / relative_path;
|
|
105
|
+
} except ValueError {
|
|
106
|
+
output_path = self.compiled_dir / js_path.name;
|
|
107
|
+
}
|
|
108
|
+
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
109
|
+
output_path.write_text(js_code, encoding='utf-8');
|
|
110
|
+
} except FileNotFoundError { }
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
"""Recursively compile/copy .jac/.js imports to temp, skipping bundling."""
|
|
114
|
+
impl ViteCompiler.compile_dependencies_recursively(
|
|
115
|
+
self: ViteCompiler,
|
|
116
|
+
module_path: Path,
|
|
117
|
+
visited: (set[Path] | None) = None,
|
|
118
|
+
collected_exports: (set[str] | None) = None,
|
|
119
|
+
collected_globals: (dict[(str, Any)] | None) = None,
|
|
120
|
+
source_root: (Path | None) = None
|
|
121
|
+
) -> None {
|
|
122
|
+
if (visited is None) {
|
|
123
|
+
visited = set();
|
|
124
|
+
}
|
|
125
|
+
if (collected_exports is None) {
|
|
126
|
+
collected_exports = set();
|
|
127
|
+
}
|
|
128
|
+
if (collected_globals is None) {
|
|
129
|
+
collected_globals = {};
|
|
130
|
+
}
|
|
131
|
+
module_path = module_path.resolve();
|
|
132
|
+
if (module_path in visited) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
visited.add(module_path);
|
|
136
|
+
if (source_root is None) {
|
|
137
|
+
source_root = module_path.parent.resolve();
|
|
138
|
+
}
|
|
139
|
+
(module_js, mod, manifest) = self.jac_compiler.compile_module(module_path);
|
|
140
|
+
exports_list = self.jac_compiler.extract_exports(manifest);
|
|
141
|
+
collected_exports.update(exports_list);
|
|
142
|
+
non_root_globals: dict[(str, Any)] = {};
|
|
143
|
+
if manifest {
|
|
144
|
+
for name in manifest.globals {
|
|
145
|
+
non_root_globals[name] = manifest.globals_values.get(name);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
collected_globals.update(non_root_globals);
|
|
149
|
+
combined_js = self.jac_compiler.add_runtime_imports(module_js);
|
|
150
|
+
try {
|
|
151
|
+
relative_path = module_path.relative_to(source_root);
|
|
152
|
+
output_path = self.compiled_dir / relative_path.with_suffix('.js');
|
|
153
|
+
} except ValueError {
|
|
154
|
+
output_path = self.compiled_dir / f"{module_path.stem}.js";
|
|
155
|
+
}
|
|
156
|
+
output_path.parent.mkdir(parents=True, exist_ok=True);
|
|
157
|
+
output_path.write_text(combined_js, encoding='utf-8');
|
|
158
|
+
if (not manifest or not manifest.imports) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
for (_name, import_path) in manifest.imports.items() {
|
|
162
|
+
path_obj = Path(import_path).resolve();
|
|
163
|
+
if (path_obj in visited) {
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (path_obj.suffix == '.jac') {
|
|
167
|
+
self.compile_dependencies_recursively(
|
|
168
|
+
path_obj,
|
|
169
|
+
visited,
|
|
170
|
+
collected_exports=collected_exports,
|
|
171
|
+
collected_globals=collected_globals,
|
|
172
|
+
source_root=source_root
|
|
173
|
+
);
|
|
174
|
+
} elif (path_obj.suffix == '.js') {
|
|
175
|
+
self._copy_js_file(path_obj, source_root);
|
|
176
|
+
} elif (path_obj.suffix in {'.ts','.tsx'}) {
|
|
177
|
+
self._copy_ts_file(path_obj, source_root);
|
|
178
|
+
} elif path_obj.is_file() {
|
|
179
|
+
self._copy_asset_file(path_obj, source_root);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
"""Compile client runtime utilities."""
|
|
185
|
+
impl ViteCompiler.compile_runtime_utils(self: ViteCompiler) -> tuple[str, list[str]] {
|
|
186
|
+
if not self.runtime_path {
|
|
187
|
+
raise ClientBundleError('Runtime path not set') ;
|
|
188
|
+
}
|
|
189
|
+
runtime_utils_path = self.runtime_path.parent / 'client_runtime.cl.jac';
|
|
190
|
+
(runtimeutils_js, mod, runtimeutils_manifest) = self.jac_compiler.compile_module(
|
|
191
|
+
runtime_utils_path
|
|
192
|
+
);
|
|
193
|
+
runtimeutils_exports_list = self.jac_compiler.extract_exports(
|
|
194
|
+
runtimeutils_manifest
|
|
195
|
+
);
|
|
196
|
+
all_exports = sorted(set((runtimeutils_exports_list + self.ROUTER_EXPORTS)));
|
|
197
|
+
combined_runtime_utils_js = runtimeutils_js;
|
|
198
|
+
self.compiled_dir.mkdir(parents=True, exist_ok=True);
|
|
199
|
+
(self.compiled_dir / 'client_runtime.js').write_text(
|
|
200
|
+
combined_runtime_utils_js, encoding='utf-8'
|
|
201
|
+
);
|
|
202
|
+
return (combined_runtime_utils_js, all_exports);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
"""Initialize the Vite compiler."""
|
|
206
|
+
impl ViteCompiler.init(
|
|
207
|
+
self: ViteCompiler,
|
|
208
|
+
vite_package_json: Path,
|
|
209
|
+
vite_output_dir: (Path | None) = None,
|
|
210
|
+
vite_minify: bool = False,
|
|
211
|
+
runtime_path: (Path | None) = None,
|
|
212
|
+
compile_to_js_func: (Callable[([Path], tuple[(str, (ModuleType | None))])] | None) = None,
|
|
213
|
+
extract_exports_func: (Callable[([Any], list[str])] | None) = None,
|
|
214
|
+
extract_globals_func: (Callable[([Any, ModuleType], dict[(str, Any)])] | None) = None
|
|
215
|
+
) {
|
|
216
|
+
if (not vite_package_json or not vite_package_json.exists()) {
|
|
217
|
+
raise ClientBundleError(
|
|
218
|
+
'Vite package.json not found. Set vite_package_json when using ViteCompiler'
|
|
219
|
+
) ;
|
|
220
|
+
}
|
|
221
|
+
if (
|
|
222
|
+
(compile_to_js_func is None)
|
|
223
|
+
or (extract_exports_func is None)
|
|
224
|
+
or (extract_globals_func is None)
|
|
225
|
+
) {
|
|
226
|
+
raise ClientBundleError(
|
|
227
|
+
'compile_to_js_func, extract_exports_func, and extract_globals_func are required'
|
|
228
|
+
) ;
|
|
229
|
+
}
|
|
230
|
+
self.vite_package_json = vite_package_json;
|
|
231
|
+
# If package.json is in .client-build/.jac-client.configs/, go up two levels to get project root
|
|
232
|
+
if (
|
|
233
|
+
vite_package_json.parent.name == '.jac-client.configs'
|
|
234
|
+
and vite_package_json.parent.parent.name == '.client-build'
|
|
235
|
+
) {
|
|
236
|
+
self.project_dir = vite_package_json.parent.parent.parent;
|
|
237
|
+
} elif (vite_package_json.parent.name == '.jac-client.configs') {
|
|
238
|
+
self.project_dir = vite_package_json.parent.parent;
|
|
239
|
+
} else {
|
|
240
|
+
self.project_dir = vite_package_json.parent;
|
|
241
|
+
}
|
|
242
|
+
self.runtime_path = runtime_path;
|
|
243
|
+
self.compiled_dir = self.project_dir / '.client-build' / 'compiled';
|
|
244
|
+
self.jac_compiler = JacToJSCompiler(
|
|
245
|
+
compile_to_js_func, extract_exports_func, extract_globals_func
|
|
246
|
+
);
|
|
247
|
+
self.import_processor = ImportProcessor();
|
|
248
|
+
self.asset_processor = AssetProcessor();
|
|
249
|
+
self.babel_processor = BabelProcessor(self.project_dir);
|
|
250
|
+
self.vite_bundler = ViteBundler(self.project_dir, vite_output_dir, vite_minify);
|
|
251
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Implementation of Jac Client configuration loader.
|
|
2
|
+
|
|
3
|
+
This module provides the implementation for JacClientConfig, which inherits
|
|
4
|
+
from PluginConfigBase for common configuration loading functionality.
|
|
5
|
+
|
|
6
|
+
The base class handles: init, get_jac_config, get_section.
|
|
7
|
+
This file implements plugin-specific methods including a custom load()
|
|
8
|
+
that combines plugin config with npm dependencies.
|
|
9
|
+
"""
|
|
10
|
+
import from pathlib { Path }
|
|
11
|
+
import from typing { Any }
|
|
12
|
+
import from jaclang.project.plugin_config { deep_merge }
|
|
13
|
+
|
|
14
|
+
"""Get the plugin section name for client."""
|
|
15
|
+
impl JacClientConfig.get_plugin_name(self: JacClientConfig) -> str {
|
|
16
|
+
return "client";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
"""Get default configuration structure for client."""
|
|
20
|
+
impl JacClientConfig.get_default_config(self: JacClientConfig) -> dict[str, Any] {
|
|
21
|
+
return {
|
|
22
|
+
'vite': {
|
|
23
|
+
'plugins': [],
|
|
24
|
+
'lib_imports': [],
|
|
25
|
+
'build': {},
|
|
26
|
+
'server': {},
|
|
27
|
+
'resolve': {}
|
|
28
|
+
},
|
|
29
|
+
'ts': {'compilerOptions': {}, 'include': [], 'exclude': []},
|
|
30
|
+
'package': {
|
|
31
|
+
'name': '',
|
|
32
|
+
'version': '1.0.0',
|
|
33
|
+
'description': '',
|
|
34
|
+
'dependencies': {},
|
|
35
|
+
'devDependencies': {}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
"""Load configuration from jac.toml, merging with defaults.
|
|
41
|
+
|
|
42
|
+
Overrides base class to also include npm dependencies from [dependencies.npm].
|
|
43
|
+
"""
|
|
44
|
+
impl JacClientConfig.load(self: JacClientConfig) -> dict[str, Any] {
|
|
45
|
+
if self._config is not None {
|
|
46
|
+
return self._config;
|
|
47
|
+
}
|
|
48
|
+
default_config = self.get_default_config();
|
|
49
|
+
jac_config = self.get_jac_config();
|
|
50
|
+
# Get client plugin config from [plugins.client]
|
|
51
|
+
client_config = jac_config.get_plugin_config('client');
|
|
52
|
+
# Get npm dependencies from [dependencies.npm]
|
|
53
|
+
npm_deps = jac_config.get_plugin_deps('npm');
|
|
54
|
+
# Get npm dev dependencies from [dev-dependencies.npm]
|
|
55
|
+
# These are stored in plugin_dependencies["npm"]["dev"] after parsing
|
|
56
|
+
npm_plugin_deps = jac_config.plugin_dependencies.get('npm', {});
|
|
57
|
+
npm_dev_deps = npm_plugin_deps.get('dev', {})
|
|
58
|
+
if isinstance(npm_plugin_deps.get('dev'), dict)
|
|
59
|
+
else {};
|
|
60
|
+
# Build user config in the expected internal format
|
|
61
|
+
user_config: dict[str, Any] = {
|
|
62
|
+
'vite': client_config.get('vite', {}),
|
|
63
|
+
'ts': client_config.get('ts', {}),
|
|
64
|
+
'package': {
|
|
65
|
+
'name': jac_config.project.name,
|
|
66
|
+
'version': jac_config.project.version,
|
|
67
|
+
'description': jac_config.project.description,
|
|
68
|
+
'dependencies': npm_deps,
|
|
69
|
+
'devDependencies': npm_dev_deps
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
self._config = deep_merge(default_config, user_config);
|
|
73
|
+
return self._config;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
"""Get package configuration (npm dependencies)."""
|
|
77
|
+
impl JacClientConfig.get_package_config(self: JacClientConfig) -> dict[str, Any] {
|
|
78
|
+
config = self.load();
|
|
79
|
+
return config.get('package', {});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
"""Get Vite-specific configuration."""
|
|
83
|
+
impl JacClientConfig.get_vite_config(self: JacClientConfig) -> dict[str, Any] {
|
|
84
|
+
config = self.load();
|
|
85
|
+
return config.get('vite', {});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
"""Get TypeScript-specific configuration for tsconfig.json customization."""
|
|
89
|
+
impl JacClientConfig.get_ts_config(self: JacClientConfig) -> dict[str, Any] {
|
|
90
|
+
config = self.load();
|
|
91
|
+
return config.get('ts', {});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
"""Save configuration back to jac.toml using core JacConfig."""
|
|
95
|
+
impl JacClientConfig.save(self: JacClientConfig) -> None {
|
|
96
|
+
jac_config = self.get_jac_config();
|
|
97
|
+
jac_config.save();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
"""Add an npm dependency."""
|
|
101
|
+
impl JacClientConfig.add_dependency(
|
|
102
|
+
self: JacClientConfig, name: str, version: str, is_dev: bool = False
|
|
103
|
+
) -> None {
|
|
104
|
+
jac_config = self.get_jac_config();
|
|
105
|
+
jac_config.add_dependency(name, version, dev=is_dev, dep_type="npm");
|
|
106
|
+
# Invalidate cache
|
|
107
|
+
self.invalidate();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
"""Remove an npm dependency."""
|
|
111
|
+
impl JacClientConfig.remove_dependency(
|
|
112
|
+
self: JacClientConfig, name: str, is_dev: bool = False
|
|
113
|
+
) -> bool {
|
|
114
|
+
jac_config = self.get_jac_config();
|
|
115
|
+
result = jac_config.remove_dependency(name, dev=is_dev, dep_type="npm");
|
|
116
|
+
# Invalidate cache
|
|
117
|
+
self.invalidate();
|
|
118
|
+
return result;
|
|
119
|
+
}
|