jac-client 0.2.6__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/{src/button.jac → button.jac} +4 -3
- jac_client/examples/all-in-one/components/CategoryFilter.jac +47 -0
- jac_client/examples/all-in-one/components/Header.jac +17 -0
- jac_client/examples/all-in-one/components/ProfitOverview.jac +64 -0
- jac_client/examples/all-in-one/components/Summary.jac +76 -0
- jac_client/examples/all-in-one/components/TransactionForm.jac +188 -0
- jac_client/examples/all-in-one/components/TransactionItem.jac +62 -0
- jac_client/examples/all-in-one/components/TransactionList.jac +44 -0
- jac_client/examples/all-in-one/components/button.jac +8 -0
- jac_client/examples/all-in-one/components/navigation.jac +126 -0
- jac_client/examples/all-in-one/constants/categories.jac +36 -0
- jac_client/examples/all-in-one/constants/clients.jac +12 -0
- jac_client/examples/all-in-one/context/BudgetContext.jac +31 -0
- jac_client/examples/all-in-one/hooks/useBudget.jac +122 -0
- jac_client/examples/all-in-one/hooks/useLocalStorage.jac +37 -0
- jac_client/examples/all-in-one/main.jac +542 -0
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +140 -0
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +157 -0
- jac_client/examples/all-in-one/pages/LandingPage.jac +124 -0
- 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 +127 -0
- jac_client/examples/all-in-one/pages/nestedDemo.jac +54 -0
- jac_client/examples/all-in-one/pages/notFound.jac +18 -0
- jac_client/examples/all-in-one/pages/signupPage.jac +127 -0
- jac_client/examples/all-in-one/utils/formatters.jac +49 -0
- 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 +507 -470
- jac_client/plugin/client.jac +30 -12
- jac_client/plugin/client_runtime.cl.jac +25 -15
- jac_client/plugin/impl/client.impl.jac +126 -26
- jac_client/plugin/impl/client_runtime.impl.jac +182 -10
- jac_client/plugin/plugin_config.jac +216 -34
- jac_client/plugin/src/__init__.jac +0 -2
- jac_client/plugin/src/compiler.jac +2 -2
- 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 +99 -30
- 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 +384 -144
- jac_client/plugin/src/package_installer.jac +1 -1
- 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 +15 -1
- 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 +110 -52
- jac_client/tests/fixtures/spawn_test/app.jac +64 -70
- jac_client/tests/fixtures/with-ts/app.jac +28 -28
- jac_client/tests/test_cli.py +280 -113
- jac_client/tests/test_e2e.py +232 -0
- jac_client/tests/test_helpers.py +58 -0
- jac_client/tests/test_it.py +325 -154
- jac_client/tests/test_it_desktop.py +891 -0
- {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/METADATA +20 -11
- jac_client-0.2.11.dist-info/RECORD +113 -0
- {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/WHEEL +1 -1
- jac_client/examples/all-in-one/src/app.jac +0 -841
- jac_client/examples/all-in-one/src/components/button.jac +0 -7
- 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 -377
- jac_client/examples/basic-auth-with-router/src/app.jac +0 -464
- jac_client/examples/basic-full-stack/src/app.jac +0 -365
- 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 -84
- jac_client-0.2.6.dist-info/RECORD +0 -74
- {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/entry_points.txt +0 -0
- {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/top_level.txt +0 -0
jac_client/plugin/cli.jac
CHANGED
|
@@ -1,547 +1,584 @@
|
|
|
1
1
|
"""Command line interface tool for the Jac Client.
|
|
2
2
|
|
|
3
|
-
This module extends
|
|
4
|
-
|
|
3
|
+
This module extends core CLI commands to add the --npm flag for
|
|
4
|
+
client-side (frontend) package management:
|
|
5
|
+
- `jac add --npm`: Add npm dependencies
|
|
6
|
+
- `jac remove --npm`: Remove npm dependencies
|
|
7
|
+
|
|
8
|
+
For creating client projects, use: `jac create --use client`
|
|
5
9
|
"""
|
|
6
10
|
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import sys;
|
|
10
|
-
import pathlib;
|
|
11
|
-
import subprocess;
|
|
12
|
-
import shutil;
|
|
13
|
-
import from jaclang.cli.cmdreg { cmd_registry, CommandPriority }
|
|
11
|
+
import from jaclang.cli.registry { get_registry }
|
|
12
|
+
import from jaclang.cli.command { Arg, ArgKind, HookContext }
|
|
14
13
|
import from jaclang.pycore.runtime { hookimpl }
|
|
15
|
-
import
|
|
14
|
+
import os;
|
|
15
|
+
|
|
16
|
+
glob registry = get_registry();
|
|
17
|
+
|
|
18
|
+
# Register targets when module loads
|
|
19
|
+
# Import base target classes - this should trigger annex pass to auto-discover .impl.jac files
|
|
20
|
+
import from jac_client.plugin.src.targets.desktop_target {
|
|
21
|
+
DesktopTarget
|
|
22
|
+
}
|
|
23
|
+
import from jac_client.plugin.src.targets.web_target { WebTarget }
|
|
24
|
+
import from jac_client.plugin.src.targets.register { register_targets }
|
|
25
|
+
|
|
26
|
+
with entry {
|
|
27
|
+
register_targets();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
"""Register 'build' command at module level."""
|
|
31
|
+
@registry.command(
|
|
32
|
+
name="build",
|
|
33
|
+
help="Build a Jac application for a specific target",
|
|
34
|
+
args=[
|
|
35
|
+
Arg.create(
|
|
36
|
+
"filename",
|
|
37
|
+
kind=ArgKind.POSITIONAL,
|
|
38
|
+
default="main.jac",
|
|
39
|
+
help="Path to .jac file (default: main.jac)"
|
|
40
|
+
),
|
|
41
|
+
Arg.create(
|
|
42
|
+
"client",
|
|
43
|
+
typ=str,
|
|
44
|
+
default="web",
|
|
45
|
+
help="Build client (web, desktop)",
|
|
46
|
+
choices=["web", "desktop"],
|
|
47
|
+
short="" # Disable auto-generated -t (may conflict with other plugins)
|
|
48
|
+
),
|
|
49
|
+
Arg.create(
|
|
50
|
+
"platform",
|
|
51
|
+
typ=str,
|
|
52
|
+
default=None,
|
|
53
|
+
help="Platform for desktop builds (windows, macos, linux, all)",
|
|
54
|
+
choices=["windows", "macos", "linux", "all"],
|
|
55
|
+
short="p" # Use -p for platform
|
|
56
|
+
),
|
|
57
|
+
|
|
58
|
+
],
|
|
59
|
+
examples=[
|
|
60
|
+
("jac build", "Build web target (default)"),
|
|
61
|
+
("jac build main.jac", "Build specific file"),
|
|
62
|
+
("jac build --client desktop", "Build desktop app"),
|
|
63
|
+
("jac build --client desktop --platform windows", "Build for Windows"),
|
|
64
|
+
|
|
65
|
+
],
|
|
66
|
+
group="build",
|
|
67
|
+
source="jac-client"
|
|
68
|
+
)
|
|
69
|
+
def build(
|
|
70
|
+
filename: str = "main.jac", target: str = "web", platform: str | None = None
|
|
71
|
+
) -> int {
|
|
72
|
+
# This will be handled by the pre_hook
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
"""Register 'setup' command at module level."""
|
|
77
|
+
@registry.command(
|
|
78
|
+
name="setup",
|
|
79
|
+
help="Setup a build target (one-time initialization)",
|
|
80
|
+
args=[
|
|
81
|
+
Arg.create(
|
|
82
|
+
"target", kind=ArgKind.POSITIONAL, help="Target to setup (e.g., desktop)"
|
|
83
|
+
),
|
|
84
|
+
|
|
85
|
+
],
|
|
86
|
+
examples=[("jac setup desktop", "Setup desktop target (Tauri)"), ],
|
|
87
|
+
group="project",
|
|
88
|
+
source="jac-client"
|
|
89
|
+
)
|
|
90
|
+
def setup(target: str) -> int {
|
|
91
|
+
# This will be handled by the pre_hook
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
16
94
|
|
|
17
95
|
"""Jac CLI extensions for client-side development."""
|
|
18
96
|
class JacCmd {
|
|
19
97
|
"""Create Jac CLI cmds."""
|
|
20
98
|
@hookimpl
|
|
21
99
|
static def create_cmd -> None {
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
skip: Skip installing default packages (only for --cl projects)
|
|
41
|
-
verbose: Show detailed output during package installation
|
|
42
|
-
|
|
43
|
-
Examples:
|
|
44
|
-
jac create
|
|
45
|
-
jac create myapp
|
|
46
|
-
jac create --cl myapp
|
|
47
|
-
jac create --cl --skip myapp
|
|
48
|
-
jac create --cl --verbose myapp
|
|
49
|
-
jac create --force
|
|
50
|
-
""";
|
|
51
|
-
cwd = pathlib.Path(os.getcwd());
|
|
52
|
-
|
|
53
|
-
if cl {
|
|
54
|
-
_create_client_project(cwd, name, force, skip, verbose);
|
|
55
|
-
} else {
|
|
56
|
-
_create_core_project(cwd, name, force);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
100
|
+
"""Extend core commands to add --npm flag for npm package management.""";
|
|
101
|
+
registry = get_registry();
|
|
102
|
+
|
|
103
|
+
# Extend the core 'create' command with --skip flag for client template
|
|
104
|
+
registry.extend_command(
|
|
105
|
+
command_name="create",
|
|
106
|
+
args=[
|
|
107
|
+
Arg.create(
|
|
108
|
+
"skip",
|
|
109
|
+
typ=bool,
|
|
110
|
+
default=False,
|
|
111
|
+
help="Skip npm package installation (for --use client)"
|
|
112
|
+
),
|
|
113
|
+
|
|
114
|
+
],
|
|
115
|
+
pre_hook=_handle_create_skip,
|
|
116
|
+
source="jac-client"
|
|
117
|
+
);
|
|
59
118
|
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
119
|
+
# Extend the core 'add' command with --npm flag
|
|
120
|
+
registry.extend_command(
|
|
121
|
+
command_name="add",
|
|
122
|
+
args=[
|
|
123
|
+
Arg.create(
|
|
124
|
+
"npm",
|
|
125
|
+
typ=bool,
|
|
126
|
+
default=False,
|
|
127
|
+
help="Add as npm (client-side) dependency"
|
|
128
|
+
),
|
|
129
|
+
|
|
130
|
+
],
|
|
131
|
+
pre_hook=_handle_npm_add,
|
|
132
|
+
source="jac-client"
|
|
63
133
|
);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
134
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
135
|
+
# Extend the core 'remove' command with --npm flag
|
|
136
|
+
registry.extend_command(
|
|
137
|
+
command_name="remove",
|
|
138
|
+
args=[
|
|
139
|
+
Arg.create(
|
|
140
|
+
"npm",
|
|
141
|
+
typ=bool,
|
|
142
|
+
default=False,
|
|
143
|
+
help="Remove npm (client-side) dependency"
|
|
144
|
+
),
|
|
145
|
+
|
|
146
|
+
],
|
|
147
|
+
pre_hook=_handle_npm_remove,
|
|
148
|
+
source="jac-client"
|
|
149
|
+
);
|
|
76
150
|
|
|
77
|
-
|
|
151
|
+
# Add pre-hook to build command (command is registered at module level)
|
|
152
|
+
registry.extend_command(
|
|
153
|
+
command_name="build", pre_hook=_handle_build_target, source="jac-client"
|
|
154
|
+
);
|
|
78
155
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
156
|
+
# Add pre-hook to setup command (command is registered at module level)
|
|
157
|
+
registry.extend_command(
|
|
158
|
+
command_name="setup", pre_hook=_handle_setup_target, source="jac-client"
|
|
159
|
+
);
|
|
84
160
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
161
|
+
# Extend 'start' command with --client flag
|
|
162
|
+
# Note: jac-scale also uses --client, so we use --client to avoid conflict
|
|
163
|
+
if registry.has_command("start") {
|
|
164
|
+
registry.extend_command(
|
|
165
|
+
command_name="start",
|
|
166
|
+
args=[
|
|
167
|
+
Arg.create(
|
|
168
|
+
"client", # Use client to avoid conflict with jac-scale's --client
|
|
169
|
+
typ=str,
|
|
170
|
+
default="web",
|
|
171
|
+
help="Client build target for dev server (web, desktop)",
|
|
172
|
+
choices=["web", "desktop"],
|
|
173
|
+
short="" # Disable auto-generated short flag
|
|
174
|
+
),
|
|
175
|
+
|
|
176
|
+
],
|
|
177
|
+
pre_hook=_handle_start_target,
|
|
178
|
+
source="jac-client"
|
|
101
179
|
);
|
|
102
180
|
}
|
|
103
|
-
print(f"Created {main_jac}");
|
|
104
181
|
}
|
|
182
|
+
}
|
|
105
183
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
184
|
+
"""Pre-hook to handle --skip flag for create command."""
|
|
185
|
+
def _handle_create_skip(ctx: HookContext) -> None {
|
|
186
|
+
# Check if --skip flag is set
|
|
187
|
+
skip_flag = ctx.get_arg("skip", False);
|
|
188
|
+
if skip_flag {
|
|
189
|
+
# Set environment variable to skip npm installation
|
|
190
|
+
os.environ["JAC_CLIENT_SKIP_NPM_INSTALL"] = "1";
|
|
110
191
|
}
|
|
192
|
+
# Let core create command run normally
|
|
193
|
+
}
|
|
111
194
|
|
|
112
|
-
|
|
195
|
+
"""Pre-hook to handle --npm flag for adding npm dependencies."""
|
|
196
|
+
def _handle_npm_add(ctx: HookContext) -> None {
|
|
197
|
+
# Check if --npm flag is set
|
|
198
|
+
npm_flag = ctx.get_arg("npm", False);
|
|
199
|
+
if not npm_flag {
|
|
200
|
+
# Let core add command run normally
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
113
203
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
print(" jac install # Install all dependencies");
|
|
119
|
-
}
|
|
204
|
+
import from jaclang.project.config { get_config }
|
|
205
|
+
import from jaclang.project.dep_registry { get_dependency_registry }
|
|
206
|
+
import from jaclang.project.dependencies { DependencyResolver }
|
|
207
|
+
import from jaclang.cli.console { console }
|
|
120
208
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
force: bool,
|
|
126
|
-
skip: bool = False,
|
|
127
|
-
verbose: bool = False
|
|
128
|
-
) -> None {
|
|
129
|
-
project_name = name or cwd.name;
|
|
130
|
-
|
|
131
|
-
if not project_name or project_name == 'main' {
|
|
132
|
-
print(
|
|
133
|
-
"Error: Project name is required for client projects. Use: jac create --cl <name>",
|
|
134
|
-
file=sys.stderr
|
|
209
|
+
config = get_config();
|
|
210
|
+
if config is None {
|
|
211
|
+
console.error(
|
|
212
|
+
"No jac.toml found", hint="Run 'jac create' to create a project."
|
|
135
213
|
);
|
|
136
|
-
|
|
214
|
+
ctx.set_data("cancel_execution", True);
|
|
215
|
+
ctx.set_data("cancel_return_code", 1);
|
|
216
|
+
return;
|
|
137
217
|
}
|
|
138
218
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
219
|
+
registry = get_dependency_registry();
|
|
220
|
+
dep_type = registry.get_by_flag("--npm");
|
|
221
|
+
if dep_type is None {
|
|
222
|
+
console.error(
|
|
223
|
+
"--npm flag requires jac-client plugin",
|
|
224
|
+
hint="Install with: pip install jac-client"
|
|
143
225
|
);
|
|
144
|
-
|
|
226
|
+
ctx.set_data("cancel_execution", True);
|
|
227
|
+
ctx.set_data("cancel_return_code", 1);
|
|
228
|
+
return;
|
|
145
229
|
}
|
|
146
230
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
(project_root, toml_path) = existing;
|
|
150
|
-
print(f"Already in a Jac project: {toml_path}", file=sys.stderr);
|
|
151
|
-
print("Use --force to reinitialize.", file=sys.stderr);
|
|
152
|
-
<>exit(1);
|
|
153
|
-
}
|
|
231
|
+
packages = ctx.get_arg("packages", []);
|
|
232
|
+
dev = ctx.get_arg("dev", False);
|
|
154
233
|
|
|
155
|
-
|
|
156
|
-
if
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
234
|
+
# If no packages specified, install all npm packages from jac.toml
|
|
235
|
+
if not packages {
|
|
236
|
+
if dep_type.install_all_handler is None {
|
|
237
|
+
console.error(f"No install_all handler registered for {dep_type.name}");
|
|
238
|
+
ctx.set_data("cancel_execution", True);
|
|
239
|
+
ctx.set_data("cancel_return_code", 1);
|
|
240
|
+
return;
|
|
161
241
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
242
|
+
try {
|
|
243
|
+
console.print(
|
|
244
|
+
f"\n📦 Installing all {dep_type.name} packages from jac.toml",
|
|
245
|
+
style="bold"
|
|
246
|
+
);
|
|
247
|
+
with console.status(
|
|
248
|
+
f"[cyan]Installing {dep_type.name} packages...[/cyan]", spinner="dots"
|
|
249
|
+
) as status {
|
|
250
|
+
dep_type.install_all_handler(config);
|
|
251
|
+
}
|
|
252
|
+
console.success(f"Installed all {dep_type.name} packages");
|
|
253
|
+
ctx.set_data("cancel_execution", True);
|
|
254
|
+
ctx.set_data("cancel_return_code", 0);
|
|
255
|
+
} except Exception as e {
|
|
256
|
+
console.error(f"Failed to install packages: {e}");
|
|
257
|
+
ctx.set_data("cancel_execution", True);
|
|
258
|
+
ctx.set_data("cancel_return_code", 1);
|
|
259
|
+
}
|
|
260
|
+
return;
|
|
165
261
|
}
|
|
166
262
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# Vite bundler configuration (optional overrides)
|
|
189
|
-
# vite.plugins = []
|
|
190
|
-
# vite.build = {{}}
|
|
191
|
-
''';
|
|
192
|
-
with open(toml_path, 'w') as f {
|
|
193
|
-
f.write(toml_content);
|
|
194
|
-
}
|
|
195
|
-
print(f"Created {toml_path}");
|
|
196
|
-
|
|
197
|
-
app_jac_content = '''"""Main entry point for the Jac client application."""
|
|
198
|
-
|
|
199
|
-
# Client-side imports
|
|
200
|
-
cl import from react { useState, useEffect }
|
|
201
|
-
cl import from ".components/Button.tsx" { Button }
|
|
202
|
-
|
|
203
|
-
# Client-side component
|
|
204
|
-
cl {
|
|
205
|
-
def:pub app() -> any {
|
|
206
|
-
[count, setCount] = useState(0);
|
|
207
|
-
|
|
208
|
-
useEffect(lambda -> None {
|
|
209
|
-
console.log("Count updated:", count);
|
|
210
|
-
}, [count]);
|
|
211
|
-
|
|
212
|
-
return <div style={{padding: "2rem", fontFamily: "Arial, sans-serif"}}>
|
|
213
|
-
<h1>Hello, World!</h1>
|
|
214
|
-
<p>Count: {count}</p>
|
|
215
|
-
<div style={{display: "flex", gap: "1rem", marginTop: "1rem"}}>
|
|
216
|
-
<Button
|
|
217
|
-
label="Increment"
|
|
218
|
-
onClick={lambda -> None { setCount(count + 1); }}
|
|
219
|
-
variant="primary"
|
|
220
|
-
/>
|
|
221
|
-
<Button
|
|
222
|
-
label="Reset"
|
|
223
|
-
onClick={lambda -> None { setCount(0); }}
|
|
224
|
-
variant="secondary"
|
|
225
|
-
/>
|
|
226
|
-
</div>
|
|
227
|
-
</div>;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
''';
|
|
231
|
-
with open(src_dir / "app.jac", 'w') as f {
|
|
232
|
-
f.write(app_jac_content);
|
|
263
|
+
# Install specific packages
|
|
264
|
+
try {
|
|
265
|
+
resolver = DependencyResolver(config=config);
|
|
266
|
+
console.print(
|
|
267
|
+
f"\n📦 Adding {len(packages)} {dep_type.name} package(s)", style="bold"
|
|
268
|
+
);
|
|
269
|
+
for pkg_spec in packages {
|
|
270
|
+
(name, version) = resolver.parse_spec(pkg_spec);
|
|
271
|
+
with console.status(f"[cyan]Installing {name}...[/cyan]", spinner="dots") as status {
|
|
272
|
+
dep_type.install_handler(config, name, version, dev);
|
|
273
|
+
}
|
|
274
|
+
console.print(f" ✔ {name}", style="success");
|
|
275
|
+
}
|
|
276
|
+
section = f"dependencies.{dep_type.dev_name if dev else dep_type.name}";
|
|
277
|
+
console.print(f"\n ✔ Updated jac.toml [{section}]", style="muted");
|
|
278
|
+
ctx.set_data("cancel_execution", True);
|
|
279
|
+
ctx.set_data("cancel_return_code", 0);
|
|
280
|
+
} except Exception as e {
|
|
281
|
+
console.error(f"Failed to install packages: {e}");
|
|
282
|
+
ctx.set_data("cancel_execution", True);
|
|
283
|
+
ctx.set_data("cancel_return_code", 1);
|
|
233
284
|
}
|
|
234
|
-
print("Created src/app.jac");
|
|
235
|
-
|
|
236
|
-
button_tsx_content = '''import React from 'react';
|
|
237
|
-
|
|
238
|
-
interface ButtonProps {
|
|
239
|
-
label: string;
|
|
240
|
-
onClick?: () => void;
|
|
241
|
-
variant?: 'primary' | 'secondary';
|
|
242
|
-
disabled?: boolean;
|
|
243
285
|
}
|
|
244
286
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
},
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
return (
|
|
273
|
-
<button
|
|
274
|
-
style={{ ...baseStyles, ...variantStyles[variant] }}
|
|
275
|
-
onClick={onClick}
|
|
276
|
-
disabled={disabled}
|
|
277
|
-
>
|
|
278
|
-
{label}
|
|
279
|
-
</button>
|
|
280
|
-
);
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
export default Button;
|
|
284
|
-
''';
|
|
285
|
-
with open(components_dir / "Button.tsx", 'w') as f {
|
|
286
|
-
f.write(button_tsx_content);
|
|
287
|
+
"""Pre-hook to handle --client flag for build command."""
|
|
288
|
+
def _handle_build_target(ctx: HookContext) -> None {
|
|
289
|
+
import from jaclang.cli.console { console }
|
|
290
|
+
import from jac_client.plugin.src.targets.registry { get_target_registry }
|
|
291
|
+
import from pathlib { Path }
|
|
292
|
+
import from jaclang.project.config { get_config }
|
|
293
|
+
|
|
294
|
+
target_name = ctx.get_arg("client", "web");
|
|
295
|
+
platform = ctx.get_arg("platform", None);
|
|
296
|
+
|
|
297
|
+
registry = get_target_registry();
|
|
298
|
+
target = registry.get(target_name);
|
|
299
|
+
|
|
300
|
+
if not target {
|
|
301
|
+
console.error(f"Unknown client target: {target_name}");
|
|
302
|
+
console.print(
|
|
303
|
+
f"Available client targets: {', '.join(
|
|
304
|
+
[t.name for t in registry.get_all()]
|
|
305
|
+
)}",
|
|
306
|
+
style="muted"
|
|
307
|
+
);
|
|
308
|
+
ctx.set_data("cancel_execution", True);
|
|
309
|
+
ctx.set_data("cancel_return_code", 1);
|
|
310
|
+
return;
|
|
287
311
|
}
|
|
288
|
-
print("Created src/components/Button.tsx");
|
|
289
|
-
|
|
290
|
-
readme_content = f''' # {project_name}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
A Jac client-side application with React and TypeScript support.
|
|
294
|
-
|
|
295
|
-
## Project Structure
|
|
296
|
-
|
|
297
|
-
```
|
|
298
|
-
{project_name}/
|
|
299
|
-
├── jac.toml # Project configuration
|
|
300
|
-
├── src/ # Source files
|
|
301
|
-
│ ├── app.jac # Main application entry
|
|
302
|
-
│ └── components/ # Reusable components
|
|
303
|
-
│ └── Button.tsx # Example TypeScript component
|
|
304
|
-
├── assets/ # Static assets (images, fonts, etc.)
|
|
305
|
-
└── build/ # Build output (generated)
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
## Getting Started
|
|
309
|
-
|
|
310
|
-
Start the development server:
|
|
311
|
-
|
|
312
|
-
```bash
|
|
313
|
-
jac serve src/app.jac
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
## TypeScript Support
|
|
317
312
|
|
|
318
|
-
|
|
313
|
+
# Store target info in context for use by build handler
|
|
314
|
+
ctx.set_data("build_target", target);
|
|
315
|
+
ctx.set_data("build_platform", platform);
|
|
319
316
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
317
|
+
# If target requires setup, warn user
|
|
318
|
+
if target.requires_setup {
|
|
319
|
+
console.warning(
|
|
320
|
+
f"Client target '{target_name}' requires setup. Run 'jac setup {target_name}' first."
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
323
|
|
|
324
|
-
|
|
324
|
+
# Build using target's build method
|
|
325
|
+
try {
|
|
326
|
+
config = get_config();
|
|
327
|
+
if not config {
|
|
328
|
+
console.error("No jac.toml found. Run 'jac create' to create a project.");
|
|
329
|
+
ctx.set_data("cancel_execution", True);
|
|
330
|
+
ctx.set_data("cancel_return_code", 1);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
325
333
|
|
|
326
|
-
|
|
334
|
+
entry_file = ctx.get_arg("filename", None);
|
|
335
|
+
if not entry_file {
|
|
336
|
+
entry_file = config.entry_point;
|
|
337
|
+
}
|
|
338
|
+
if not entry_file {
|
|
339
|
+
console.error("No entry file specified. Use: jac build <file>");
|
|
340
|
+
ctx.set_data("cancel_execution", True);
|
|
341
|
+
ctx.set_data("cancel_return_code", 1);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
327
344
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
345
|
+
entry_path = Path(entry_file);
|
|
346
|
+
project_dir = config.project_root or Path.cwd();
|
|
347
|
+
if not entry_path.is_absolute() {
|
|
348
|
+
entry_path = project_dir / entry_path;
|
|
349
|
+
}
|
|
350
|
+
bundle_path = target.build(entry_path, project_dir, platform);
|
|
351
|
+
|
|
352
|
+
console.success(f"Build complete: {bundle_path}");
|
|
353
|
+
ctx.set_data("cancel_execution", True);
|
|
354
|
+
ctx.set_data("cancel_return_code", 0);
|
|
355
|
+
} except NotImplementedError as e {
|
|
356
|
+
console.error(
|
|
357
|
+
f"Target '{target_name}' is not yet implemented. Coming in Phase 2!"
|
|
358
|
+
);
|
|
359
|
+
ctx.set_data("cancel_execution", True);
|
|
360
|
+
ctx.set_data("cancel_return_code", 1);
|
|
361
|
+
} except Exception as e {
|
|
362
|
+
console.error(f"Build failed: {e}");
|
|
363
|
+
ctx.set_data("cancel_execution", True);
|
|
364
|
+
ctx.set_data("cancel_return_code", 1);
|
|
334
365
|
}
|
|
335
|
-
|
|
366
|
+
}
|
|
336
367
|
|
|
337
|
-
|
|
368
|
+
"""Pre-hook to handle --client flag for start command."""
|
|
369
|
+
def _handle_start_target(ctx: HookContext) -> None {
|
|
370
|
+
import from jaclang.cli.console { console }
|
|
371
|
+
import from jac_client.plugin.src.targets.registry { get_target_registry }
|
|
338
372
|
|
|
339
|
-
|
|
340
|
-
if not skip {
|
|
341
|
-
print("\nInstalling default packages...");
|
|
342
|
-
_install_default_packages(project_path, verbose);
|
|
343
|
-
}
|
|
373
|
+
target_name = ctx.get_arg("client", "web");
|
|
344
374
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
print("\nNext steps:");
|
|
348
|
-
print(f" cd {name}");
|
|
349
|
-
print(" jac serve src/app.jac");
|
|
350
|
-
} else {
|
|
351
|
-
print("\nNext steps:");
|
|
352
|
-
print(" jac serve src/app.jac");
|
|
353
|
-
}
|
|
354
|
-
}
|
|
375
|
+
registry = get_target_registry();
|
|
376
|
+
target = registry.get(target_name);
|
|
355
377
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
"*.jir",
|
|
364
|
-
"__jaccache__/",
|
|
365
|
-
"",
|
|
366
|
-
"# Python",
|
|
367
|
-
"__pycache__/",
|
|
368
|
-
"*.py[cod]",
|
|
369
|
-
".venv/",
|
|
370
|
-
"venv/",
|
|
371
|
-
"",
|
|
372
|
-
"# IDE",
|
|
373
|
-
".idea/",
|
|
374
|
-
".vscode/",
|
|
375
|
-
"*.swp"
|
|
376
|
-
];
|
|
377
|
-
|
|
378
|
-
if client {
|
|
379
|
-
gitignore_entries.extend(
|
|
380
|
-
[
|
|
381
|
-
"",
|
|
382
|
-
"# Node.js",
|
|
383
|
-
"node_modules/",
|
|
384
|
-
"",
|
|
385
|
-
"# Jac Client",
|
|
386
|
-
".client-build/",
|
|
387
|
-
"*.session",
|
|
388
|
-
"*.session.*"
|
|
389
|
-
]
|
|
378
|
+
if not target {
|
|
379
|
+
console.error(f"Unknown client target: {target_name}");
|
|
380
|
+
console.print(
|
|
381
|
+
f"Available client targets: {', '.join(
|
|
382
|
+
[t.name for t in registry.get_all()]
|
|
383
|
+
)}",
|
|
384
|
+
style="muted"
|
|
390
385
|
);
|
|
386
|
+
ctx.set_data("cancel_execution", True);
|
|
387
|
+
ctx.set_data("cancel_return_code", 1);
|
|
388
|
+
return;
|
|
391
389
|
}
|
|
392
390
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
391
|
+
# Store target info in context
|
|
392
|
+
ctx.set_data("start_client_target", target);
|
|
393
|
+
|
|
394
|
+
# Handle desktop target
|
|
395
|
+
if target_name == "desktop" {
|
|
396
|
+
import from pathlib { Path }
|
|
397
|
+
import from jaclang.project.config { get_config }
|
|
398
|
+
config = get_config();
|
|
399
|
+
if not config {
|
|
400
|
+
console.error("No jac.toml found. Run 'jac create' to create a project.");
|
|
401
|
+
ctx.set_data("cancel_execution", True);
|
|
402
|
+
ctx.set_data("cancel_return_code", 1);
|
|
403
|
+
return;
|
|
397
404
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
}
|
|
405
|
+
# Get entry file
|
|
406
|
+
entry_file = ctx.get_arg("filename", None);
|
|
407
|
+
if not entry_file {
|
|
408
|
+
entry_file = config.entry_point;
|
|
403
409
|
}
|
|
404
|
-
if
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
410
|
+
if not entry_file {
|
|
411
|
+
console.error("No entry file specified. Use: jac start <file>");
|
|
412
|
+
ctx.set_data("cancel_execution", True);
|
|
413
|
+
ctx.set_data("cancel_return_code", 1);
|
|
414
|
+
return;
|
|
409
415
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
416
|
+
entry_path = Path(entry_file);
|
|
417
|
+
project_dir = config.project_root or Path.cwd();
|
|
418
|
+
if not entry_path.is_absolute() {
|
|
419
|
+
entry_path = project_dir / entry_path;
|
|
413
420
|
}
|
|
414
|
-
|
|
421
|
+
# Check if setup has been run
|
|
422
|
+
tauri_dir = project_dir / "src-tauri";
|
|
423
|
+
if not tauri_dir.exists() {
|
|
424
|
+
console.error("Desktop target not set up. Run 'jac setup desktop' first.");
|
|
425
|
+
ctx.set_data("cancel_execution", True);
|
|
426
|
+
ctx.set_data("cancel_return_code", 1);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
# Check if --dev flag is set
|
|
430
|
+
dev_mode = ctx.get_arg("dev", False);
|
|
431
|
+
try {
|
|
432
|
+
if dev_mode {
|
|
433
|
+
# Desktop target with --dev: launch Tauri dev mode (hot reload)
|
|
434
|
+
target.dev(entry_path, project_dir);
|
|
435
|
+
} else {
|
|
436
|
+
# Desktop target without --dev: build web bundle and launch Tauri with built bundle
|
|
437
|
+
target.start(entry_path, project_dir);
|
|
438
|
+
}
|
|
439
|
+
ctx.set_data("cancel_execution", True);
|
|
440
|
+
ctx.set_data("cancel_return_code", 0);
|
|
441
|
+
} except Exception as e {
|
|
442
|
+
import traceback;
|
|
443
|
+
console.error(f"Desktop start failed: {e}");
|
|
444
|
+
console.print(traceback.format_exc(), style="muted");
|
|
445
|
+
ctx.set_data("cancel_execution", True);
|
|
446
|
+
ctx.set_data("cancel_return_code", 1);
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
415
449
|
}
|
|
450
|
+
# Web target: let existing start command handle it
|
|
451
|
+
# (no cancellation, let it run normally)
|
|
416
452
|
}
|
|
417
453
|
|
|
418
|
-
"""
|
|
419
|
-
def
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
import from
|
|
454
|
+
"""Pre-hook to handle setup command."""
|
|
455
|
+
def _handle_setup_target(ctx: HookContext) -> None {
|
|
456
|
+
import from jaclang.cli.console { console }
|
|
457
|
+
import from jac_client.plugin.src.targets.registry { get_target_registry }
|
|
458
|
+
import from pathlib { Path }
|
|
459
|
+
import from jaclang.project.config { get_config }
|
|
460
|
+
|
|
461
|
+
target_name = ctx.get_arg("target", None);
|
|
462
|
+
if not target_name {
|
|
463
|
+
console.error("No target specified. Use: jac setup <target>");
|
|
464
|
+
console.print("Available targets: desktop", style="muted");
|
|
465
|
+
ctx.set_data("cancel_execution", True);
|
|
466
|
+
ctx.set_data("cancel_return_code", 1);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
registry = get_target_registry();
|
|
471
|
+
target = registry.get(target_name);
|
|
472
|
+
|
|
473
|
+
if not target {
|
|
474
|
+
console.error(f"Unknown client target: {target_name}");
|
|
475
|
+
console.print(
|
|
476
|
+
f"Available targets: {', '.join([t.name for t in registry.get_all()])}",
|
|
477
|
+
style="muted"
|
|
478
|
+
);
|
|
479
|
+
ctx.set_data("cancel_execution", True);
|
|
480
|
+
ctx.set_data("cancel_return_code", 1);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
423
483
|
|
|
484
|
+
# Setup using target's setup method
|
|
424
485
|
try {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
file=sys.stderr
|
|
431
|
-
);
|
|
486
|
+
config = get_config();
|
|
487
|
+
if not config {
|
|
488
|
+
console.error("No jac.toml found. Run 'jac create' to create a project.");
|
|
489
|
+
ctx.set_data("cancel_execution", True);
|
|
490
|
+
ctx.set_data("cancel_return_code", 1);
|
|
432
491
|
return;
|
|
433
492
|
}
|
|
434
493
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
# Generate package.json with default packages (defaults are added automatically)
|
|
442
|
-
bundler.create_package_json(project_name=project_name);
|
|
443
|
-
|
|
444
|
-
# Ensure .client-build directory exists
|
|
445
|
-
build_dir = project_path / '.client-build';
|
|
446
|
-
build_dir.mkdir(parents=True, exist_ok=True);
|
|
447
|
-
|
|
448
|
-
# Copy package.json to .client-build/ for npm install
|
|
449
|
-
configs_package_json = build_dir / '.jac-client.configs' / 'package.json';
|
|
450
|
-
build_package_json = build_dir / 'package.json';
|
|
494
|
+
project_dir = config.project_root or Path.cwd();
|
|
495
|
+
console.print(
|
|
496
|
+
f"Setting up target '{target_name}' in: {project_dir}", style="muted"
|
|
497
|
+
);
|
|
498
|
+
target.setup(project_dir);
|
|
451
499
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
500
|
+
# Verify setup completed successfully
|
|
501
|
+
tauri_dir = project_dir / "src-tauri";
|
|
502
|
+
if not tauri_dir.exists() {
|
|
503
|
+
console.error(
|
|
504
|
+
f"Setup completed but src-tauri directory not found at: {tauri_dir}"
|
|
456
505
|
);
|
|
506
|
+
console.print(
|
|
507
|
+
"This may indicate the setup function failed silently.", style="muted"
|
|
508
|
+
);
|
|
509
|
+
ctx.set_data("cancel_execution", True);
|
|
510
|
+
ctx.set_data("cancel_return_code", 1);
|
|
457
511
|
return;
|
|
458
512
|
}
|
|
459
513
|
|
|
460
|
-
|
|
461
|
-
|
|
514
|
+
console.success(f"Target '{target_name}' setup complete!");
|
|
515
|
+
ctx.set_data("cancel_execution", True);
|
|
516
|
+
ctx.set_data("cancel_return_code", 0);
|
|
517
|
+
} except NotImplementedError as e {
|
|
518
|
+
console.error(f"Target '{target_name}' setup is not yet implemented.");
|
|
519
|
+
ctx.set_data("cancel_execution", True);
|
|
520
|
+
ctx.set_data("cancel_return_code", 1);
|
|
521
|
+
} except Exception as e {
|
|
522
|
+
import traceback;
|
|
523
|
+
console.error(f"Setup failed: {e}");
|
|
524
|
+
console.print(traceback.format_exc(), style="muted");
|
|
525
|
+
ctx.set_data("cancel_execution", True);
|
|
526
|
+
ctx.set_data("cancel_return_code", 1);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
462
529
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if verbose {
|
|
472
|
-
# Verbose mode: show detailed package list and stream npm output
|
|
473
|
-
if deps {
|
|
474
|
-
print(" Dependencies:");
|
|
475
|
-
for (name, version) in deps.items() {
|
|
476
|
-
print(f" - {name}@{version}");
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
if dev_deps {
|
|
480
|
-
print(" Dev dependencies:");
|
|
481
|
-
for (name, version) in dev_deps.items() {
|
|
482
|
-
print(f" - {name}@{version}");
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
print("\nRunning npm install...");
|
|
486
|
-
}
|
|
530
|
+
"""Pre-hook to handle --npm flag for removing npm dependencies."""
|
|
531
|
+
def _handle_npm_remove(ctx: HookContext) -> None {
|
|
532
|
+
# Check if --npm flag is set
|
|
533
|
+
npm_flag = ctx.get_arg("npm", False);
|
|
534
|
+
if not npm_flag {
|
|
535
|
+
# Let core remove command run normally
|
|
536
|
+
return;
|
|
537
|
+
}
|
|
487
538
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
# Stream output for visibility in verbose mode
|
|
492
|
-
subprocess.run(
|
|
493
|
-
['npm', 'install', '--progress'], cwd=build_dir, check=True
|
|
494
|
-
);
|
|
495
|
-
} else {
|
|
496
|
-
# Quiet mode: capture output
|
|
497
|
-
subprocess.run(
|
|
498
|
-
['npm', 'install'],
|
|
499
|
-
cwd=build_dir,
|
|
500
|
-
check=True,
|
|
501
|
-
capture_output=True,
|
|
502
|
-
text=True
|
|
503
|
-
);
|
|
504
|
-
}
|
|
539
|
+
import from jaclang.project.config { get_config }
|
|
540
|
+
import from jaclang.project.dep_registry { get_dependency_registry }
|
|
541
|
+
import from jaclang.cli.console { console }
|
|
505
542
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
configs_package_lock.unlink();
|
|
514
|
-
}
|
|
515
|
-
shutil.move(str(build_package_lock), str(configs_package_lock));
|
|
516
|
-
}
|
|
543
|
+
config = get_config();
|
|
544
|
+
if config is None {
|
|
545
|
+
console.error("No jac.toml found. Run 'jac create' to create a project.");
|
|
546
|
+
ctx.set_data("cancel_execution", True);
|
|
547
|
+
ctx.set_data("cancel_return_code", 1);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
517
550
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
551
|
+
packages = ctx.get_arg("packages", []);
|
|
552
|
+
if not packages {
|
|
553
|
+
console.error("No packages specified.");
|
|
554
|
+
ctx.set_data("cancel_execution", True);
|
|
555
|
+
ctx.set_data("cancel_return_code", 1);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
registry = get_dependency_registry();
|
|
560
|
+
dep_type = registry.get_by_flag("--npm");
|
|
561
|
+
if dep_type is None {
|
|
562
|
+
console.error("--npm flag requires jac-client plugin to be installed.");
|
|
563
|
+
console.print("Install with: pip install jac-client", style="muted");
|
|
564
|
+
ctx.set_data("cancel_execution", True);
|
|
565
|
+
ctx.set_data("cancel_return_code", 1);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
dev = ctx.get_arg("dev", False);
|
|
570
|
+
|
|
571
|
+
try {
|
|
572
|
+
for name in packages {
|
|
573
|
+
console.info(f"Removing {name} ({dep_type.name})...");
|
|
574
|
+
dep_type.remove_handler(config, name, dev);
|
|
542
575
|
}
|
|
576
|
+
console.success(f"Removed {len(packages)} package(s)");
|
|
577
|
+
ctx.set_data("cancel_execution", True);
|
|
578
|
+
ctx.set_data("cancel_return_code", 0);
|
|
543
579
|
} except Exception as e {
|
|
544
|
-
|
|
545
|
-
|
|
580
|
+
console.error(f"Error removing packages: {e}");
|
|
581
|
+
ctx.set_data("cancel_execution", True);
|
|
582
|
+
ctx.set_data("cancel_return_code", 1);
|
|
546
583
|
}
|
|
547
584
|
}
|