jac-client 0.1.0__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/docs/README.md +629 -0
- jac_client/docs/advanced-state.md +706 -0
- jac_client/docs/imports.md +650 -0
- jac_client/docs/lifecycle-hooks.md +554 -0
- jac_client/docs/routing.md +530 -0
- jac_client/examples/little-x/app.jac +615 -0
- jac_client/examples/little-x/package-lock.json +2840 -0
- jac_client/examples/little-x/package.json +23 -0
- jac_client/examples/little-x/submit-button.jac +8 -0
- jac_client/examples/todo-app/README.md +82 -0
- jac_client/examples/todo-app/app.jac +683 -0
- jac_client/examples/todo-app/package-lock.json +999 -0
- jac_client/examples/todo-app/package.json +22 -0
- jac_client/plugin/cli.py +328 -0
- jac_client/plugin/client.py +41 -0
- jac_client/plugin/client_runtime.jac +941 -0
- jac_client/plugin/vite_client_bundle.py +470 -0
- jac_client/tests/__init__.py +2 -0
- jac_client/tests/fixtures/button.jac +6 -0
- jac_client/tests/fixtures/client_app.jac +18 -0
- jac_client/tests/fixtures/client_app_with_antd.jac +21 -0
- jac_client/tests/fixtures/js_import.jac +30 -0
- jac_client/tests/fixtures/package-lock.json +329 -0
- jac_client/tests/fixtures/package.json +11 -0
- jac_client/tests/fixtures/relative_import.jac +13 -0
- jac_client/tests/fixtures/test_fragments_spread.jac +44 -0
- jac_client/tests/fixtures/utils.js +22 -0
- jac_client/tests/test_cl.py +360 -0
- jac_client/tests/test_create_jac_app.py +139 -0
- jac_client-0.1.0.dist-info/METADATA +126 -0
- jac_client-0.1.0.dist-info/RECORD +33 -0
- jac_client-0.1.0.dist-info/WHEEL +4 -0
- jac_client-0.1.0.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "todo-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "vite build",
|
|
7
|
+
"dev": "vite dev",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"description": "Jac application: todo-app",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"vite": "^5.0.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"react": "^18.2.0",
|
|
20
|
+
"react-dom": "^18.2.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
jac_client/plugin/cli.py
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"""Command line interface tool for the Jac Client."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from jaclang.cli.cmdreg import cmd_registry
|
|
10
|
+
from jaclang.runtimelib.machine import hookimpl
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class JacCmd:
|
|
14
|
+
"""Jac CLI."""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
@hookimpl
|
|
18
|
+
def create_cmd() -> None:
|
|
19
|
+
"""Create Jac CLI cmds."""
|
|
20
|
+
|
|
21
|
+
@cmd_registry.register
|
|
22
|
+
def create_jac_app(name: str) -> None:
|
|
23
|
+
"""Create a new Jac application with npm and Vite setup.
|
|
24
|
+
|
|
25
|
+
Bootstraps a new Jac project by creating a temporary directory, initializing
|
|
26
|
+
npm, installing Vite, and setting up the basic project structure.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
name: Name of the project to create
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
jac create_jac_app my-app
|
|
33
|
+
jac create_jac_app my-jac-project
|
|
34
|
+
"""
|
|
35
|
+
if not name:
|
|
36
|
+
print(
|
|
37
|
+
"Error: Project name is required. Use --name=your-project-name",
|
|
38
|
+
file=sys.stderr,
|
|
39
|
+
)
|
|
40
|
+
exit(1)
|
|
41
|
+
|
|
42
|
+
# Validate project name (basic npm package name validation)
|
|
43
|
+
if not re.match(r"^[a-zA-Z0-9_-]+$", name):
|
|
44
|
+
print(
|
|
45
|
+
"Error: Project name must contain only letters, numbers, hyphens, and underscores",
|
|
46
|
+
file=sys.stderr,
|
|
47
|
+
)
|
|
48
|
+
exit(1)
|
|
49
|
+
|
|
50
|
+
print(f"Creating new Jac application: {name}")
|
|
51
|
+
|
|
52
|
+
# Create project directory in current working directory
|
|
53
|
+
project_path = os.path.join(os.getcwd(), name)
|
|
54
|
+
|
|
55
|
+
if os.path.exists(project_path):
|
|
56
|
+
print(
|
|
57
|
+
f"Error: Directory '{name}' already exists in current location",
|
|
58
|
+
file=sys.stderr,
|
|
59
|
+
)
|
|
60
|
+
exit(1)
|
|
61
|
+
|
|
62
|
+
os.makedirs(project_path, exist_ok=True)
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
# Change to project directory
|
|
66
|
+
original_cwd = os.getcwd()
|
|
67
|
+
os.chdir(project_path)
|
|
68
|
+
|
|
69
|
+
# Initialize npm package
|
|
70
|
+
print("Initializing npm package...")
|
|
71
|
+
npm_init_cmd = ["npm", "init", "-y"]
|
|
72
|
+
subprocess.run(npm_init_cmd, capture_output=True, text=True, check=True)
|
|
73
|
+
|
|
74
|
+
# Read the generated package.json
|
|
75
|
+
package_json_path = os.path.join(project_path, "package.json")
|
|
76
|
+
with open(package_json_path, "r") as f:
|
|
77
|
+
package_data = json.load(f)
|
|
78
|
+
|
|
79
|
+
# create temp folder
|
|
80
|
+
temp_folder = os.path.join(project_path, "temp")
|
|
81
|
+
os.makedirs(temp_folder, exist_ok=True)
|
|
82
|
+
|
|
83
|
+
# create static/client/js folder
|
|
84
|
+
client_js_folder = os.path.join(project_path, "static", "client", "js")
|
|
85
|
+
os.makedirs(client_js_folder, exist_ok=True)
|
|
86
|
+
|
|
87
|
+
# Update package.json with Jac-specific configuration
|
|
88
|
+
package_data.update(
|
|
89
|
+
{
|
|
90
|
+
"name": name,
|
|
91
|
+
"description": f"Jac application: {name}",
|
|
92
|
+
"type": "module",
|
|
93
|
+
"scripts": {
|
|
94
|
+
"build": "vite build",
|
|
95
|
+
"dev": "vite dev",
|
|
96
|
+
"preview": "vite preview",
|
|
97
|
+
},
|
|
98
|
+
"devDependencies": {"vite": "^5.0.0"},
|
|
99
|
+
"dependencies": {"react": "^18.2.0", "react-dom": "^18.2.0"},
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Write updated package.json
|
|
104
|
+
with open(package_json_path, "w") as f:
|
|
105
|
+
json.dump(package_data, f, indent=2)
|
|
106
|
+
|
|
107
|
+
print("Installing Vite...")
|
|
108
|
+
# Install Vite
|
|
109
|
+
npm_install_cmd = ["npm", "install"]
|
|
110
|
+
subprocess.run(
|
|
111
|
+
npm_install_cmd, capture_output=True, text=True, check=True
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Create basic project structure
|
|
115
|
+
print("Setting up project structure...")
|
|
116
|
+
|
|
117
|
+
# Create a basic Jac file
|
|
118
|
+
main_jac_content = """
|
|
119
|
+
# Pages
|
|
120
|
+
cl def HomeView() -> any {
|
|
121
|
+
return <div
|
|
122
|
+
style={{
|
|
123
|
+
"minHeight": "100vh",
|
|
124
|
+
"fontFamily": "-apple-system, BlinkMacSystemFont, sans-serif"
|
|
125
|
+
}}>
|
|
126
|
+
<main
|
|
127
|
+
style={{
|
|
128
|
+
"maxWidth": "1200px",
|
|
129
|
+
"margin": "0 auto",
|
|
130
|
+
"padding": "60px 40px"
|
|
131
|
+
}}>
|
|
132
|
+
<div
|
|
133
|
+
style={{
|
|
134
|
+
"textAlign": "center",
|
|
135
|
+
"marginBottom": "80px"
|
|
136
|
+
}}>
|
|
137
|
+
<h1
|
|
138
|
+
style={{
|
|
139
|
+
"fontSize": "56px",
|
|
140
|
+
"marginBottom": "20px"
|
|
141
|
+
}}>
|
|
142
|
+
Welcome to
|
|
143
|
+
<span style={{"color": "#007bff"}}>OneLang</span>
|
|
144
|
+
</h1>
|
|
145
|
+
<p
|
|
146
|
+
style={{
|
|
147
|
+
"fontSize": "20px",
|
|
148
|
+
"color": "#666"
|
|
149
|
+
}}>
|
|
150
|
+
One Language. One Stack. Zero Friction.
|
|
151
|
+
</p>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<div
|
|
155
|
+
style={{
|
|
156
|
+
"display": "grid",
|
|
157
|
+
"gridTemplateColumns": "repeat(2, 1fr)",
|
|
158
|
+
"gap": "24px",
|
|
159
|
+
"marginBottom": "60px"
|
|
160
|
+
}}>
|
|
161
|
+
<a
|
|
162
|
+
href="https://docs.jaseci.org"
|
|
163
|
+
target="_blank"
|
|
164
|
+
style={{
|
|
165
|
+
"padding": "32px",
|
|
166
|
+
"backgroundColor": "white",
|
|
167
|
+
"border": "1px solid #eaeaea",
|
|
168
|
+
"borderRadius": "8px",
|
|
169
|
+
"textDecoration": "none",
|
|
170
|
+
"color": "#000"
|
|
171
|
+
}}>
|
|
172
|
+
<h3
|
|
173
|
+
style={{
|
|
174
|
+
"marginTop": "0",
|
|
175
|
+
"marginBottom": "12px"
|
|
176
|
+
}}>📖 Documentation</h3>
|
|
177
|
+
<p style={{"color": "#666", "margin": "0"}}>
|
|
178
|
+
Learn how to build with OneLang
|
|
179
|
+
</p>
|
|
180
|
+
</a>
|
|
181
|
+
<a
|
|
182
|
+
href="https://docs.jaseci.org/learn"
|
|
183
|
+
target="_blank"
|
|
184
|
+
style={{
|
|
185
|
+
"padding": "32px",
|
|
186
|
+
"backgroundColor": "white",
|
|
187
|
+
"border": "1px solid #eaeaea",
|
|
188
|
+
"borderRadius": "8px",
|
|
189
|
+
"textDecoration": "none",
|
|
190
|
+
"color": "#000"
|
|
191
|
+
}}>
|
|
192
|
+
<h3
|
|
193
|
+
style={{
|
|
194
|
+
"marginTop": "0",
|
|
195
|
+
"marginBottom": "12px"
|
|
196
|
+
}}>🎓 Learn</h3>
|
|
197
|
+
<p style={{"color": "#666", "margin": "0"}}>
|
|
198
|
+
Tutorials and guides
|
|
199
|
+
</p>
|
|
200
|
+
</a>
|
|
201
|
+
<a
|
|
202
|
+
href="/examples"
|
|
203
|
+
style={{
|
|
204
|
+
"padding": "32px",
|
|
205
|
+
"backgroundColor": "white",
|
|
206
|
+
"border": "1px solid #eaeaea",
|
|
207
|
+
"borderRadius": "8px",
|
|
208
|
+
"textDecoration": "none",
|
|
209
|
+
"color": "#000"
|
|
210
|
+
}}>
|
|
211
|
+
<h3
|
|
212
|
+
style={{
|
|
213
|
+
"marginTop": "0",
|
|
214
|
+
"marginBottom": "12px"
|
|
215
|
+
}}>💡 Examples</h3>
|
|
216
|
+
<p style={{"color": "#666", "margin": "0"}}>
|
|
217
|
+
Sample applications
|
|
218
|
+
</p>
|
|
219
|
+
</a>
|
|
220
|
+
<a
|
|
221
|
+
href="https://github.com/Jaseci-Labs/jaseci"
|
|
222
|
+
target="_blank"
|
|
223
|
+
style={{
|
|
224
|
+
"padding": "32px",
|
|
225
|
+
"backgroundColor": "white",
|
|
226
|
+
"border": "1px solid #eaeaea",
|
|
227
|
+
"borderRadius": "8px",
|
|
228
|
+
"textDecoration": "none",
|
|
229
|
+
"color": "#000"
|
|
230
|
+
}}>
|
|
231
|
+
<h3
|
|
232
|
+
style={{
|
|
233
|
+
"marginTop": "0",
|
|
234
|
+
"marginBottom": "12px"
|
|
235
|
+
}}>🔧 Community</h3>
|
|
236
|
+
<p style={{"color": "#666", "margin": "0"}}>
|
|
237
|
+
GitHub repository
|
|
238
|
+
</p>
|
|
239
|
+
</a>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<footer
|
|
243
|
+
style={{
|
|
244
|
+
"borderTop": "1px solid #eaeaea",
|
|
245
|
+
"paddingTop": "40px",
|
|
246
|
+
"textAlign": "center",
|
|
247
|
+
"color": "#999"
|
|
248
|
+
}}>
|
|
249
|
+
<p>
|
|
250
|
+
Get started by editing
|
|
251
|
+
<code
|
|
252
|
+
style={{
|
|
253
|
+
"backgroundColor": "#f5f5f5",
|
|
254
|
+
"padding": "2px 6px",
|
|
255
|
+
"borderRadius": "3px"
|
|
256
|
+
}}>app.jac</code>
|
|
257
|
+
</p>
|
|
258
|
+
</footer>
|
|
259
|
+
</main>
|
|
260
|
+
</div>;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# Main App component with declarative router
|
|
265
|
+
cl def App() -> any {
|
|
266
|
+
|
|
267
|
+
home_route = {
|
|
268
|
+
"path": "/",
|
|
269
|
+
"component": lambda -> any { return HomeView(); },
|
|
270
|
+
"guard": None
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
routes = [home_route];
|
|
274
|
+
router = initRouter(routes, "/");
|
|
275
|
+
|
|
276
|
+
# add all the wrapper components here
|
|
277
|
+
return <div class="app-container">
|
|
278
|
+
{router.render()}
|
|
279
|
+
</div>;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
# Main SPA entry point - simplified with reactive routing
|
|
283
|
+
cl def jac_app() -> any {
|
|
284
|
+
return App();
|
|
285
|
+
}
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
with open(os.path.join(project_path, "app.jac"), "w") as f:
|
|
289
|
+
f.write(main_jac_content)
|
|
290
|
+
|
|
291
|
+
# Create README.md
|
|
292
|
+
readme_content = f"""# {name}
|
|
293
|
+
|
|
294
|
+
## Running Jac Code
|
|
295
|
+
|
|
296
|
+
To run your Jac code, use the Jac CLI:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
jac serve app.jac
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Happy coding with Jac!
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
with open(os.path.join(project_path, "README.md"), "w") as f:
|
|
306
|
+
f.write(readme_content)
|
|
307
|
+
|
|
308
|
+
# Return to original directory
|
|
309
|
+
os.chdir(original_cwd)
|
|
310
|
+
|
|
311
|
+
print(f"✅ Successfully created Jac application '{name}'!")
|
|
312
|
+
print(f"📁 Project location: {os.path.abspath(project_path)}")
|
|
313
|
+
print("\nNext steps:")
|
|
314
|
+
print(f" cd {name}")
|
|
315
|
+
print(" jac serve app.jac")
|
|
316
|
+
|
|
317
|
+
except subprocess.CalledProcessError as e:
|
|
318
|
+
# Return to original directory on error
|
|
319
|
+
os.chdir(original_cwd)
|
|
320
|
+
print(f"Error running npm command: {e}", file=sys.stderr)
|
|
321
|
+
print(f"Command output: {e.stdout}", file=sys.stderr)
|
|
322
|
+
print(f"Command error: {e.stderr}", file=sys.stderr)
|
|
323
|
+
exit(1)
|
|
324
|
+
except Exception as e:
|
|
325
|
+
# Return to original directory on error
|
|
326
|
+
os.chdir(original_cwd)
|
|
327
|
+
print(f"Error creating project: {e}", file=sys.stderr)
|
|
328
|
+
exit(1)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import types
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from jaclang.runtimelib.client_bundle import ClientBundle
|
|
5
|
+
from jaclang.runtimelib.machine import (
|
|
6
|
+
JacMachine as Jac,
|
|
7
|
+
hookimpl,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from .vite_client_bundle import ViteClientBundleBuilder
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class JacClient:
|
|
14
|
+
"""Jac Client."""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
@hookimpl
|
|
18
|
+
def get_client_bundle_builder() -> ViteClientBundleBuilder:
|
|
19
|
+
"""Get the client bundle builder instance."""
|
|
20
|
+
base_path = Path(Jac.base_path_dir)
|
|
21
|
+
package_json_path = base_path / "package.json"
|
|
22
|
+
output_dir = base_path / "static" / "client" / "js"
|
|
23
|
+
# Use the plugin's client_runtime.jac file
|
|
24
|
+
runtime_path = Path(__file__).with_name("client_runtime.jac")
|
|
25
|
+
print(f"Runtime path: {runtime_path}")
|
|
26
|
+
return ViteClientBundleBuilder(
|
|
27
|
+
runtime_path=runtime_path,
|
|
28
|
+
vite_package_json=package_json_path,
|
|
29
|
+
vite_output_dir=output_dir,
|
|
30
|
+
vite_minify=False,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
@hookimpl
|
|
35
|
+
def build_client_bundle(
|
|
36
|
+
module: types.ModuleType,
|
|
37
|
+
force: bool = False,
|
|
38
|
+
) -> ClientBundle:
|
|
39
|
+
"""Build a client bundle for the supplied module."""
|
|
40
|
+
builder = JacClient.get_client_bundle_builder()
|
|
41
|
+
return builder.build(module, force=force)
|