jac-client 0.2.4__py3-none-any.whl → 0.2.5__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.
Files changed (70) hide show
  1. jac_client/examples/all-in-one/src/app.jac +841 -0
  2. jac_client/examples/all-in-one/src/button.jac +7 -0
  3. jac_client/examples/all-in-one/src/components/button.jac +7 -0
  4. jac_client/examples/asset-serving/css-with-image/src/app.jac +88 -0
  5. jac_client/examples/asset-serving/image-asset/src/app.jac +55 -0
  6. jac_client/examples/asset-serving/import-alias/src/app.jac +111 -0
  7. jac_client/examples/basic/src/app.jac +21 -0
  8. jac_client/examples/basic-auth/src/app.jac +377 -0
  9. jac_client/examples/basic-auth-with-router/src/app.jac +464 -0
  10. jac_client/examples/basic-full-stack/src/app.jac +365 -0
  11. jac_client/examples/css-styling/js-styling/src/app.jac +84 -0
  12. jac_client/examples/css-styling/material-ui/src/app.jac +122 -0
  13. jac_client/examples/css-styling/pure-css/src/app.jac +64 -0
  14. jac_client/examples/css-styling/sass-example/src/app.jac +64 -0
  15. jac_client/examples/css-styling/styled-components/src/app.jac +71 -0
  16. jac_client/examples/css-styling/tailwind-example/src/app.jac +63 -0
  17. jac_client/examples/full-stack-with-auth/src/app.jac +722 -0
  18. jac_client/examples/little-x/src/app.jac +719 -0
  19. jac_client/examples/little-x/src/submit-button.jac +16 -0
  20. jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +11 -0
  21. jac_client/examples/nested-folders/nested-advance/src/app.jac +35 -0
  22. jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +19 -0
  23. jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +43 -0
  24. jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +25 -0
  25. jac_client/examples/nested-folders/nested-basic/src/app.jac +13 -0
  26. jac_client/examples/nested-folders/nested-basic/src/button.jac +7 -0
  27. jac_client/examples/nested-folders/nested-basic/src/components/button.jac +7 -0
  28. jac_client/examples/ts-support/src/app.jac +35 -0
  29. jac_client/examples/with-router/src/app.jac +323 -0
  30. jac_client/plugin/cli.jac +547 -0
  31. jac_client/plugin/client.jac +52 -0
  32. jac_client/plugin/client_runtime.cl.jac +38 -0
  33. jac_client/plugin/impl/client.impl.jac +134 -0
  34. jac_client/plugin/impl/client_runtime.impl.jac +177 -0
  35. jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
  36. jac_client/plugin/plugin_config.jac +195 -0
  37. jac_client/plugin/src/__init__.jac +20 -0
  38. jac_client/plugin/src/asset_processor.jac +33 -0
  39. jac_client/plugin/src/babel_processor.jac +18 -0
  40. jac_client/plugin/src/compiler.jac +66 -0
  41. jac_client/plugin/src/config_loader.jac +32 -0
  42. jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
  43. jac_client/plugin/src/impl/babel_processor.impl.jac +84 -0
  44. jac_client/plugin/src/impl/compiler.impl.jac +251 -0
  45. jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
  46. jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
  47. jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
  48. jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
  49. jac_client/plugin/src/impl/vite_bundler.impl.jac +513 -0
  50. jac_client/plugin/src/import_processor.jac +19 -0
  51. jac_client/plugin/src/jac_to_js.jac +35 -0
  52. jac_client/plugin/src/package_installer.jac +26 -0
  53. jac_client/plugin/src/vite_bundler.jac +36 -0
  54. jac_client/plugin/vite_client_bundle.jac +31 -0
  55. jac_client/tests/fixtures/basic-app/app.jac +23 -0
  56. jac_client/tests/fixtures/cl_file/app.cl.jac +48 -0
  57. jac_client/tests/fixtures/cl_file/app.jac +15 -0
  58. jac_client/tests/fixtures/client_app_with_antd/app.jac +34 -0
  59. jac_client/tests/fixtures/js_import/app.jac +34 -0
  60. jac_client/tests/fixtures/relative_import/app.jac +11 -0
  61. jac_client/tests/fixtures/relative_import/button.jac +7 -0
  62. jac_client/tests/fixtures/spawn_test/app.jac +129 -0
  63. jac_client/tests/fixtures/test_fragments_spread/app.jac +67 -0
  64. jac_client/tests/fixtures/with-ts/app.jac +35 -0
  65. {jac_client-0.2.4.dist-info → jac_client-0.2.5.dist-info}/METADATA +2 -2
  66. jac_client-0.2.5.dist-info/RECORD +74 -0
  67. jac_client-0.2.4.dist-info/RECORD +0 -10
  68. {jac_client-0.2.4.dist-info → jac_client-0.2.5.dist-info}/WHEEL +0 -0
  69. {jac_client-0.2.4.dist-info → jac_client-0.2.5.dist-info}/entry_points.txt +0 -0
  70. {jac_client-0.2.4.dist-info → jac_client-0.2.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,547 @@
1
+ """Command line interface tool for the Jac Client.
2
+
3
+ This module extends the core `create` command to add client-side (frontend)
4
+ project setup via the --cl flag.
5
+ """
6
+
7
+ import os;
8
+ import re;
9
+ import sys;
10
+ import pathlib;
11
+ import subprocess;
12
+ import shutil;
13
+ import from jaclang.cli.cmdreg { cmd_registry, CommandPriority }
14
+ import from jaclang.pycore.runtime { hookimpl }
15
+ import from jaclang.project.config { JacConfig, find_project_root }
16
+
17
+ """Jac CLI extensions for client-side development."""
18
+ class JacCmd {
19
+ """Create Jac CLI cmds."""
20
+ @hookimpl
21
+ static def create_cmd -> None {
22
+ """Override core create command to add --cl flag for client-side setup.""";
23
+
24
+ def create(
25
+ name: str = 'main',
26
+ force: bool = False,
27
+ cl: bool = False,
28
+ skip: bool = False,
29
+ verbose: bool = False
30
+ ) -> None {
31
+ """Initialize a new Jac project.
32
+
33
+ Creates a jac.toml configuration file and basic project structure.
34
+ Use --cl to include client-side (frontend) setup with Vite bundling.
35
+
36
+ Args:
37
+ name: Project name (default: 'main')
38
+ force: Overwrite existing jac.toml if present
39
+ cl: Include client-side (frontend) setup
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
+ }
59
+
60
+ # Register with PLUGIN priority to override core's create command
61
+ cmd_registry.register(
62
+ create, priority=CommandPriority.PLUGIN, source="jac-client"
63
+ );
64
+ }
65
+ }
66
+
67
+ """Create a standard Jac project (core behavior)."""
68
+ def _create_core_project(cwd: pathlib.Path, name: str, force: bool) -> None {
69
+ existing = find_project_root(cwd);
70
+ if existing and not force {
71
+ (project_root, toml_path) = existing;
72
+ print(f"Already in a Jac project: {toml_path}", file=sys.stderr);
73
+ print("Use --force to reinitialize.", file=sys.stderr);
74
+ <>exit(1);
75
+ }
76
+
77
+ project_name = name or cwd.name;
78
+
79
+ toml_path = cwd / "jac.toml";
80
+ if toml_path.exists() and not force {
81
+ print("jac.toml already exists. Use --force to overwrite.", file=sys.stderr);
82
+ <>exit(1);
83
+ }
84
+
85
+ toml_content = JacConfig.create_default_toml(project_name);
86
+ with open(toml_path, "w") as f {
87
+ f.write(toml_content);
88
+ }
89
+ print(f"Created {toml_path}");
90
+
91
+ main_jac = cwd / f"{name}.jac";
92
+ if not main_jac.exists() {
93
+ with open(main_jac, "w") as f {
94
+ f.write(
95
+ f'''"""Main entry point for {project_name}."""
96
+
97
+ with entry {{
98
+ print("Hello from {project_name}!");
99
+ }}
100
+ '''
101
+ );
102
+ }
103
+ print(f"Created {main_jac}");
104
+ }
105
+
106
+ packages_dir = cwd / "packages";
107
+ if not packages_dir.exists() {
108
+ packages_dir.mkdir(parents=True, exist_ok=True);
109
+ print(f"Created {packages_dir}/");
110
+ }
111
+
112
+ _create_gitignore(cwd, client=False);
113
+
114
+ print(f"\nProject '{project_name}' initialized successfully!");
115
+ print("\nNext steps:");
116
+ print(" jac run main.jac # Run the main entry point");
117
+ print(" jac add <package> # Add dependencies");
118
+ print(" jac install # Install all dependencies");
119
+ }
120
+
121
+ """Create a client-side Jac project with organized folder structure."""
122
+ def _create_client_project(
123
+ cwd: pathlib.Path,
124
+ name: str,
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
135
+ );
136
+ <>exit(1);
137
+ }
138
+
139
+ if not re.match('^[a-zA-Z0-9_-]+$', project_name) {
140
+ print(
141
+ "Error: Project name must contain only letters, numbers, hyphens, and underscores",
142
+ file=sys.stderr
143
+ );
144
+ <>exit(1);
145
+ }
146
+
147
+ existing = find_project_root(cwd);
148
+ if existing and not force {
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
+ }
154
+
155
+ project_path: pathlib.Path;
156
+ if name and name != cwd.name {
157
+ project_path = cwd / name;
158
+ if project_path.exists() and not force {
159
+ print(f"Error: Directory '{name}' already exists", file=sys.stderr);
160
+ <>exit(1);
161
+ }
162
+ project_path.mkdir(parents=True, exist_ok=True);
163
+ } else {
164
+ project_path = cwd;
165
+ }
166
+
167
+ print(f"Creating Jac client application: {project_name}");
168
+
169
+ src_dir = project_path / "src";
170
+ src_dir.mkdir(parents=True, exist_ok=True);
171
+
172
+ components_dir = src_dir / "components";
173
+ components_dir.mkdir(parents=True, exist_ok=True);
174
+
175
+ assets_dir = project_path / "assets";
176
+ assets_dir.mkdir(parents=True, exist_ok=True);
177
+
178
+ (project_path / ".client-build").mkdir(parents=True, exist_ok=True);
179
+
180
+ toml_path = project_path / "jac.toml";
181
+ toml_content = f'''[project]
182
+ name = "{project_name}"
183
+ version = "1.0.0"
184
+ description = "Jac client application: {project_name}"
185
+ entry-point = "src/app.jac"
186
+
187
+ [plugins.client]
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);
233
+ }
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
+ }
244
+
245
+ export const Button: React.FC<ButtonProps> = ({
246
+ label,
247
+ onClick,
248
+ variant = 'primary',
249
+ disabled = false
250
+ }) => {
251
+ const baseStyles: React.CSSProperties = {
252
+ padding: '0.75rem 1.5rem',
253
+ fontSize: '1rem',
254
+ fontWeight: '600',
255
+ borderRadius: '0.5rem',
256
+ border: 'none',
257
+ cursor: disabled ? 'not-allowed' : 'pointer',
258
+ transition: 'all 0.2s ease',
259
+ };
260
+
261
+ const variantStyles: Record<string, React.CSSProperties> = {
262
+ primary: {
263
+ backgroundColor: disabled ? '#9ca3af' : '#3b82f6',
264
+ color: '#ffffff',
265
+ },
266
+ secondary: {
267
+ backgroundColor: disabled ? '#e5e7eb' : '#6b7280',
268
+ color: '#ffffff',
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
+ }
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
+
318
+ Create TypeScript components in `src/components/` and import them in your Jac files:
319
+
320
+ ```jac
321
+ cl import from "./components/Button.tsx" {{ Button }}
322
+ ```
323
+
324
+ ## Adding Dependencies
325
+
326
+ Add npm packages with the --cl flag:
327
+
328
+ ```bash
329
+ jac add --cl react-router-dom
330
+ ```
331
+ ''';
332
+ with open(project_path / "README.md", 'w') as f {
333
+ f.write(readme_content);
334
+ }
335
+ print("Created README.md");
336
+
337
+ _create_gitignore(project_path, client=True);
338
+
339
+ # Install default packages unless --skip is specified
340
+ if not skip {
341
+ print("\nInstalling default packages...");
342
+ _install_default_packages(project_path, verbose);
343
+ }
344
+
345
+ print(f"\nProject '{project_name}' created successfully!");
346
+ if name and name != cwd.name {
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
+ }
355
+
356
+ """Create .gitignore file with appropriate entries."""
357
+ def _create_gitignore(project_path: pathlib.Path, client: bool = False) -> None {
358
+ gitignore_entries = [
359
+ "# Jac project",
360
+ "packages/",
361
+ ".jac_cache/",
362
+ "*.jbc",
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
+ ]
390
+ );
391
+ }
392
+
393
+ gitignore_path = project_path / ".gitignore";
394
+ if gitignore_path.exists() {
395
+ with open(gitignore_path, "r") as f {
396
+ existing_content = f.read();
397
+ }
398
+ new_entries: list = [];
399
+ for entry in gitignore_entries {
400
+ if entry and entry not in existing_content {
401
+ new_entries.append(entry);
402
+ }
403
+ }
404
+ if new_entries {
405
+ with open(gitignore_path, "a") as f {
406
+ f.write("\n" + "\n".join(new_entries));
407
+ }
408
+ print("Updated .gitignore");
409
+ }
410
+ } else {
411
+ with open(gitignore_path, "w") as f {
412
+ f.write("\n".join(gitignore_entries) + "\n");
413
+ }
414
+ print("Created .gitignore");
415
+ }
416
+ }
417
+
418
+ """Install default npm packages in .client-build directory."""
419
+ def _install_default_packages(
420
+ project_path: pathlib.Path, verbose: bool = False
421
+ ) -> None {
422
+ import from jac_client.plugin.src.vite_bundler { ViteBundler }
423
+
424
+ try {
425
+ # Verify jac.toml exists
426
+ toml_path = project_path / "jac.toml";
427
+ if not toml_path.exists() {
428
+ print(
429
+ "Warning: jac.toml not found, skipping package installation",
430
+ file=sys.stderr
431
+ );
432
+ return;
433
+ }
434
+
435
+ # Get project name from jac.toml or use directory name
436
+ project_name = project_path.name;
437
+
438
+ # Create ViteBundler instance (it will load config internally)
439
+ bundler = ViteBundler(project_path);
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';
451
+
452
+ if not configs_package_json.exists() {
453
+ print(
454
+ "Warning: package.json was not generated, skipping package installation",
455
+ file=sys.stderr
456
+ );
457
+ return;
458
+ }
459
+
460
+ # Always copy the generated package.json to .client-build/ for npm install
461
+ shutil.copy2(configs_package_json, build_package_json);
462
+
463
+ # Read package data for verbose output
464
+ import json;
465
+ with open(configs_package_json, 'r') as f {
466
+ pkg_data = json.load(f);
467
+ }
468
+ deps = pkg_data.get('dependencies', {});
469
+ dev_deps = pkg_data.get('devDependencies', {});
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
+ }
487
+
488
+ # Run npm install in .client-build/ directory
489
+ try {
490
+ if verbose {
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
+ }
505
+
506
+ # Move package-lock.json to .jac-client.configs/ if it was created
507
+ build_package_lock = build_dir / 'package-lock.json';
508
+ configs_dir = build_dir / '.jac-client.configs';
509
+ configs_package_lock = configs_dir / 'package-lock.json';
510
+ if build_package_lock.exists() {
511
+ configs_dir.mkdir(parents=True, exist_ok=True);
512
+ if configs_package_lock.exists() {
513
+ configs_package_lock.unlink();
514
+ }
515
+ shutil.move(str(build_package_lock), str(configs_package_lock));
516
+ }
517
+
518
+ print("Default packages installed successfully");
519
+ } except subprocess.CalledProcessError as e {
520
+ if verbose {
521
+ print(
522
+ f"Warning: Failed to install packages (exit code {e.returncode})",
523
+ file=sys.stderr
524
+ );
525
+ } else {
526
+ print(
527
+ f"Warning: Failed to install packages: {e.stderr}", file=sys.stderr
528
+ );
529
+ }
530
+ print("You can install packages later with: jac add --cl", file=sys.stderr);
531
+ } except FileNotFoundError {
532
+ print(
533
+ "Warning: npm command not found. Install Node.js and npm to install packages.",
534
+ file=sys.stderr
535
+ );
536
+ print("You can install packages later with: jac add --cl", file=sys.stderr);
537
+ } finally {
538
+ # Clean up temporary package.json in .client-build/
539
+ if build_package_json.exists() {
540
+ build_package_json.unlink();
541
+ }
542
+ }
543
+ } except Exception as e {
544
+ print(f"Warning: Could not install default packages: {e}", file=sys.stderr);
545
+ print("You can install packages later with: jac add --cl", file=sys.stderr);
546
+ }
547
+ }
@@ -0,0 +1,52 @@
1
+ """Jac Client plugin for client-side rendering."""
2
+ import hashlib;
3
+ import html;
4
+ import mimetypes;
5
+ import types;
6
+ import from http.server { BaseHTTPRequestHandler }
7
+ import from pathlib { Path }
8
+ import from typing { Any, Literal, TypeAlias }
9
+ import from jaclang.runtimelib.client_bundle { ClientBundle, ClientBundleError }
10
+ import from jaclang.runtimelib.runtime { JacRuntime as Jac }
11
+ import from jaclang.runtimelib.runtime { hookimpl }
12
+ import from jaclang.runtimelib.server { ModuleIntrospector }
13
+ import from .vite_client_bundle { ViteClientBundleBuilder }
14
+ import from .src.vite_bundler { ViteBundler }
15
+
16
+ glob JsonValue: TypeAlias = None | str | int | float | bool | list['JsonValue'] | dict[
17
+ (str, 'JsonValue')
18
+ ],
19
+ StatusCode: TypeAlias = Literal[(200, 201, 400, 401, 404, 503)];
20
+
21
+ """Jac Client Module Introspector."""
22
+ class JacClientModuleIntrospector(ModuleIntrospector) {
23
+ def render_page(
24
+ self: JacClientModuleIntrospector,
25
+ function_name: str,
26
+ args: dict[(str, Any)],
27
+ username: str
28
+ ) -> dict[str, Any];
29
+ }
30
+
31
+ """Jac Client."""
32
+ class JacClient {
33
+ @hookimpl
34
+ static def get_client_bundle_builder -> ViteClientBundleBuilder;
35
+
36
+ @hookimpl
37
+ static def build_client_bundle(
38
+ module: types.ModuleType, force: bool = False
39
+ ) -> ClientBundle;
40
+
41
+ @hookimpl
42
+ static def get_module_introspector(
43
+ module_name: str, base_path: (str | None)
44
+ ) -> ModuleIntrospector;
45
+
46
+ @hookimpl
47
+ static def send_static_file(
48
+ handler: BaseHTTPRequestHandler,
49
+ file_path: Path,
50
+ content_type: (str | None) = None
51
+ ) -> None;
52
+ }
@@ -0,0 +1,38 @@
1
+ """Client-side runtime for Jac JSX and walker interactions."""
2
+
3
+ import from 'react' { * as React }
4
+ import from 'react-dom/client' { * as ReactDOM }
5
+ import from 'react-router-dom' {
6
+ HashRouter as ReactRouterHashRouter,
7
+ Routes as ReactRouterRoutes,
8
+ Route as ReactRouterRoute,
9
+ Link as ReactRouterLink,
10
+ Navigate as ReactRouterNavigate,
11
+ useNavigate as reactRouterUseNavigate,
12
+ useLocation as reactRouterUseLocation,
13
+ useParams as reactRouterUseParams
14
+ }
15
+
16
+ def : pub __jacJsx(tag: any, props: dict = {}, children: any = []) -> any;
17
+
18
+ glob : pub Router = ReactRouterHashRouter,
19
+ Routes = ReactRouterRoutes,
20
+ Route = ReactRouterRoute,
21
+ Link = ReactRouterLink,
22
+ Navigate = ReactRouterNavigate,
23
+ useNavigate = reactRouterUseNavigate,
24
+ useLocation = reactRouterUseLocation,
25
+ useParams = reactRouterUseParams;
26
+
27
+ def : pub useRouter -> dict;
28
+ def : pub navigate(path: str) -> None;
29
+ async def : pub __jacSpawn(left: str, right: str = "", fields: dict = {}) -> any;
30
+ def : pub jacSpawn(left: str, right: str = "", fields: dict = {}) -> any;
31
+ async def : pub __jacCallFunction(function_name: str, args: dict = {}) -> any;
32
+ async def : pub jacSignup(username: str, password: str) -> dict;
33
+ async def : pub jacLogin(username: str, password: str) -> bool;
34
+ def : pub jacLogout -> None;
35
+ def : pub jacIsLoggedIn -> bool;
36
+ def : pub __getLocalStorage(key: str) -> str;
37
+ def : pub __setLocalStorage(key: str, value: str) -> None;
38
+ def : pub __removeLocalStorage(key: str) -> None;