jac-client 0.2.6__py3-none-any.whl → 0.2.8__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 (66) hide show
  1. jac_client/examples/all-in-one/app.jac +573 -0
  2. jac_client/examples/all-in-one/components/CategoryFilter.jac +35 -0
  3. jac_client/examples/all-in-one/components/Header.jac +13 -0
  4. jac_client/examples/all-in-one/components/ProfitOverview.jac +50 -0
  5. jac_client/examples/all-in-one/components/Summary.jac +53 -0
  6. jac_client/examples/all-in-one/components/TransactionForm.jac +158 -0
  7. jac_client/examples/all-in-one/components/TransactionItem.jac +55 -0
  8. jac_client/examples/all-in-one/components/TransactionList.jac +37 -0
  9. jac_client/examples/all-in-one/components/navigation.jac +132 -0
  10. jac_client/examples/all-in-one/constants/categories.jac +37 -0
  11. jac_client/examples/all-in-one/constants/clients.jac +13 -0
  12. jac_client/examples/all-in-one/context/BudgetContext.jac +28 -0
  13. jac_client/examples/all-in-one/hooks/useBudget.jac +116 -0
  14. jac_client/examples/all-in-one/hooks/useLocalStorage.jac +36 -0
  15. jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +70 -0
  16. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +126 -0
  17. jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +552 -0
  18. jac_client/examples/all-in-one/pages/FeaturesTest.jac +126 -0
  19. jac_client/examples/all-in-one/pages/LandingPage.jac +101 -0
  20. jac_client/examples/all-in-one/pages/loginPage.jac +132 -0
  21. jac_client/examples/all-in-one/pages/nestedDemo.jac +61 -0
  22. jac_client/examples/all-in-one/pages/notFound.jac +24 -0
  23. jac_client/examples/all-in-one/pages/signupPage.jac +133 -0
  24. jac_client/examples/all-in-one/utils/formatters.jac +52 -0
  25. jac_client/examples/asset-serving/css-with-image/src/app.jac +3 -3
  26. jac_client/examples/asset-serving/image-asset/src/app.jac +3 -3
  27. jac_client/examples/asset-serving/import-alias/src/app.jac +3 -3
  28. jac_client/examples/basic/src/app.jac +3 -3
  29. jac_client/examples/basic-auth/src/app.jac +31 -37
  30. jac_client/examples/basic-auth-with-router/src/app.jac +16 -16
  31. jac_client/examples/basic-full-stack/src/app.jac +24 -30
  32. jac_client/examples/css-styling/js-styling/src/app.jac +5 -5
  33. jac_client/examples/css-styling/material-ui/src/app.jac +5 -5
  34. jac_client/examples/css-styling/pure-css/src/app.jac +5 -5
  35. jac_client/examples/css-styling/sass-example/src/app.jac +5 -5
  36. jac_client/examples/css-styling/styled-components/src/app.jac +5 -5
  37. jac_client/examples/css-styling/tailwind-example/src/app.jac +5 -5
  38. jac_client/examples/full-stack-with-auth/src/app.jac +16 -16
  39. jac_client/examples/ts-support/src/app.jac +4 -4
  40. jac_client/examples/with-router/src/app.jac +4 -4
  41. jac_client/plugin/cli.jac +160 -203
  42. jac_client/plugin/client.jac +8 -15
  43. jac_client/plugin/client_runtime.cl.jac +18 -14
  44. jac_client/plugin/impl/client.impl.jac +85 -26
  45. jac_client/plugin/impl/client_runtime.impl.jac +27 -9
  46. jac_client/plugin/plugin_config.jac +11 -11
  47. jac_client/plugin/src/compiler.jac +2 -1
  48. jac_client/plugin/src/impl/babel_processor.impl.jac +22 -17
  49. jac_client/plugin/src/impl/compiler.impl.jac +55 -18
  50. jac_client/plugin/src/impl/vite_bundler.impl.jac +215 -102
  51. jac_client/plugin/src/package_installer.jac +1 -1
  52. jac_client/plugin/src/vite_bundler.jac +9 -1
  53. jac_client/tests/conftest.py +10 -8
  54. jac_client/tests/fixtures/spawn_test/app.jac +15 -18
  55. jac_client/tests/fixtures/with-ts/app.jac +4 -4
  56. jac_client/tests/test_cli.py +105 -49
  57. jac_client/tests/test_it.py +297 -82
  58. {jac_client-0.2.6.dist-info → jac_client-0.2.8.dist-info}/METADATA +16 -7
  59. jac_client-0.2.8.dist-info/RECORD +97 -0
  60. jac_client/examples/all-in-one/src/app.jac +0 -841
  61. jac_client-0.2.6.dist-info/RECORD +0 -74
  62. /jac_client/examples/all-in-one/{src/button.jac → button.jac} +0 -0
  63. /jac_client/examples/all-in-one/{src/components → components}/button.jac +0 -0
  64. {jac_client-0.2.6.dist-info → jac_client-0.2.8.dist-info}/WHEEL +0 -0
  65. {jac_client-0.2.6.dist-info → jac_client-0.2.8.dist-info}/entry_points.txt +0 -0
  66. {jac_client-0.2.6.dist-info → jac_client-0.2.8.dist-info}/top_level.txt +0 -0
@@ -37,8 +37,8 @@ def test_create_jac_app() -> None:
37
37
  assert os.path.exists(project_path)
38
38
  assert os.path.isdir(project_path)
39
39
 
40
- # Verify src/app.jac file was created
41
- app_jac_path = os.path.join(project_path, "src", "app.jac")
40
+ # Verify main.jac file was created at project root
41
+ app_jac_path = os.path.join(project_path, "main.jac")
42
42
  assert os.path.exists(app_jac_path)
43
43
 
44
44
  with open(app_jac_path) as f:
@@ -54,7 +54,7 @@ def test_create_jac_app() -> None:
54
54
  readme_content = f.read()
55
55
 
56
56
  assert f"# {test_project_name}" in readme_content
57
- assert "jac serve src/app.jac" in readme_content
57
+ assert "jac start main.jac" in readme_content
58
58
 
59
59
  # Verify jac.toml was created
60
60
  jac_toml_path = os.path.join(project_path, "jac.toml")
@@ -65,6 +65,10 @@ def test_create_jac_app() -> None:
65
65
 
66
66
  assert config_data["project"]["name"] == test_project_name
67
67
 
68
+ # Verify serve config includes base_route_app for CL apps
69
+ assert "serve" in config_data
70
+ assert config_data["serve"]["base_route_app"] == "app"
71
+
68
72
  # Verify .gitignore was created with correct content
69
73
  gitignore_path = os.path.join(project_path, ".gitignore")
70
74
  assert os.path.exists(gitignore_path)
@@ -74,13 +78,13 @@ def test_create_jac_app() -> None:
74
78
 
75
79
  assert "node_modules" in gitignore_content
76
80
 
77
- # Verify src/components directory exists
78
- components_dir = os.path.join(project_path, "src", "components")
81
+ # Verify components directory exists at project root
82
+ components_dir = os.path.join(project_path, "components")
79
83
  assert os.path.exists(components_dir)
80
84
 
81
85
  # Verify default packages installation (package.json should be generated)
82
86
  package_json_path = os.path.join(
83
- project_path, ".client-build", ".jac-client.configs", "package.json"
87
+ project_path, ".jac", "client", "configs", "package.json"
84
88
  )
85
89
  # Note: packages may or may not be installed depending on npm availability
86
90
  # but package.json should be generated with default packages
@@ -91,9 +95,8 @@ def test_create_jac_app() -> None:
91
95
  package_data = json.load(f)
92
96
 
93
97
  # Verify default dependencies are in package.json
94
- assert "react" in package_data.get("dependencies", {})
95
- assert "react-dom" in package_data.get("dependencies", {})
96
- assert "vite" in package_data.get("devDependencies", {})
98
+ assert "jac-client-node" in package_data.get("dependencies", {})
99
+ assert "@jac-client/dev-deps" in package_data.get("devDependencies", {})
97
100
 
98
101
  finally:
99
102
  # Return to original directory
@@ -156,9 +159,9 @@ def test_create_jac_app_existing_directory() -> None:
156
159
  os.chdir(original_cwd)
157
160
 
158
161
 
159
- def test_create_jac_app_with_typescript() -> None:
160
- """Test jac create --cl command with TypeScript support (enabled by default)."""
161
- test_project_name = "test-jac-app-ts"
162
+ def test_create_jac_app_with_button_component() -> None:
163
+ """Test jac create --cl command creates Button.cl.jac component."""
164
+ test_project_name = "test-jac-app-component"
162
165
 
163
166
  # Create a temporary directory for testing
164
167
  with tempfile.TemporaryDirectory() as temp_dir:
@@ -167,7 +170,7 @@ def test_create_jac_app_with_typescript() -> None:
167
170
  # Change to temp directory
168
171
  os.chdir(temp_dir)
169
172
 
170
- # Run jac create --cl command (TypeScript is enabled by default)
173
+ # Run jac create --cl command
171
174
  process = Popen(
172
175
  ["jac", "create", "--cl", test_project_name],
173
176
  stdin=PIPE,
@@ -196,45 +199,47 @@ def test_create_jac_app_with_typescript() -> None:
196
199
 
197
200
  assert config_data["project"]["name"] == test_project_name
198
201
 
199
- # Verify src/components directory and Button.tsx were created
200
- components_dir = os.path.join(project_path, "src", "components")
202
+ # Verify serve config includes base_route_app for CL apps
203
+ assert "serve" in config_data
204
+ assert config_data["serve"]["base_route_app"] == "app"
205
+
206
+ # Verify components directory and Button.cl.jac were created at project root
207
+ components_dir = os.path.join(project_path, "components")
201
208
  assert os.path.exists(components_dir)
202
209
  assert os.path.isdir(components_dir)
203
210
 
204
- button_tsx_path = os.path.join(components_dir, "Button.tsx")
205
- assert os.path.exists(button_tsx_path)
211
+ button_jac_path = os.path.join(components_dir, "Button.cl.jac")
212
+ assert os.path.exists(button_jac_path)
206
213
 
207
- with open(button_tsx_path) as f:
214
+ with open(button_jac_path) as f:
208
215
  button_content = f.read()
209
216
 
210
- assert "interface ButtonProps" in button_content
211
- assert "export const Button" in button_content
217
+ assert "def:pub Button" in button_content
218
+ assert "base_styles" in button_content
212
219
 
213
- # Verify src/app.jac includes TypeScript import
214
- app_jac_path = os.path.join(project_path, "src", "app.jac")
220
+ # Verify main.jac includes Jac component import
221
+ app_jac_path = os.path.join(project_path, "main.jac")
215
222
  assert os.path.exists(app_jac_path)
216
223
 
217
224
  with open(app_jac_path) as f:
218
225
  app_jac_content = f.read()
219
226
 
220
- assert (
221
- 'cl import from ".components/Button.tsx" { Button }' in app_jac_content
222
- )
227
+ assert "cl import from .components.Button { Button }" in app_jac_content
223
228
  assert "<Button" in app_jac_content
224
229
 
225
- # Verify README.md includes TypeScript information
230
+ # Verify README.md includes component information
226
231
  readme_path = os.path.join(project_path, "README.md")
227
232
  assert os.path.exists(readme_path)
228
233
 
229
234
  with open(readme_path) as f:
230
235
  readme_content = f.read()
231
236
 
232
- assert "TypeScript Support" in readme_content
233
- assert "components/Button.tsx" in readme_content
237
+ assert "Components" in readme_content
238
+ assert "Button.cl.jac" in readme_content
234
239
 
235
240
  # Verify default packages installation (package.json should be generated)
236
241
  package_json_path = os.path.join(
237
- project_path, ".client-build", ".jac-client.configs", "package.json"
242
+ project_path, ".jac", "client", "configs", "package.json"
238
243
  )
239
244
  # Note: packages may or may not be installed depending on npm availability
240
245
  # but package.json should be generated with default packages
@@ -245,10 +250,8 @@ def test_create_jac_app_with_typescript() -> None:
245
250
  package_data = json.load(f)
246
251
 
247
252
  # Verify default dependencies are in package.json
248
- assert "react" in package_data.get("dependencies", {})
249
- assert "react-dom" in package_data.get("dependencies", {})
250
- assert "vite" in package_data.get("devDependencies", {})
251
- assert "typescript" in package_data.get("devDependencies", {})
253
+ assert "jac-client-node" in package_data.get("dependencies", {})
254
+ assert "@jac-client/dev-deps" in package_data.get("devDependencies", {})
252
255
 
253
256
  finally:
254
257
  # Return to original directory
@@ -334,7 +337,7 @@ def test_create_jac_app_installs_default_packages() -> None:
334
337
 
335
338
  # Verify package.json was generated (even if npm install failed)
336
339
  package_json_path = os.path.join(
337
- project_path, ".client-build", ".jac-client.configs", "package.json"
340
+ project_path, ".jac", "client", "configs", "package.json"
338
341
  )
339
342
  # package.json should be generated with default packages
340
343
  if os.path.exists(package_json_path):
@@ -343,17 +346,9 @@ def test_create_jac_app_installs_default_packages() -> None:
343
346
  with open(package_json_path) as f:
344
347
  package_data = json.load(f)
345
348
 
346
- # Verify default dependencies are in package.json
347
- deps = package_data.get("dependencies", {})
348
- dev_deps = package_data.get("devDependencies", {})
349
-
350
- assert "react" in deps
351
- assert "react-dom" in deps
352
- assert "react-router-dom" in deps
353
- assert "vite" in dev_deps
354
- assert "@babel/core" in dev_deps
355
- assert "typescript" in dev_deps
356
- assert "@types/react" in dev_deps
349
+ # Verify default dependencies are in package.
350
+ assert "jac-client-node" in package_data.get("dependencies", {})
351
+ assert "@jac-client/dev-deps" in package_data.get("devDependencies", {})
357
352
 
358
353
  finally:
359
354
  # Return to original directory
@@ -428,7 +423,7 @@ entry-point = "app.jac"
428
423
 
429
424
 
430
425
  def test_install_without_cl_flag() -> None:
431
- """Test add command without --cl flag should fail when no jac.toml exists."""
426
+ """Test add command without --cl flag should skip silently when no jac.toml exists."""
432
427
  with tempfile.TemporaryDirectory() as temp_dir:
433
428
  original_cwd = os.getcwd()
434
429
  try:
@@ -441,9 +436,11 @@ def test_install_without_cl_flag() -> None:
441
436
  text=True,
442
437
  )
443
438
 
444
- # Should fail with non-zero exit code because no jac.toml
445
- assert result.returncode != 0
446
- assert "No jac.toml found" in result.stderr
439
+ # Should skip silently (return 0) when no jac.toml exists
440
+ assert result.returncode == 0
441
+ # No error message should be printed
442
+ assert "No jac.toml found" not in result.stderr
443
+ assert "No jac.toml found" not in result.stdout
447
444
 
448
445
  finally:
449
446
  os.chdir(original_cwd)
@@ -753,3 +750,62 @@ def test_uninstall_without_config_toml() -> None:
753
750
 
754
751
  finally:
755
752
  os.chdir(original_cwd)
753
+
754
+
755
+ def test_create_cl_and_run_no_root_files() -> None:
756
+ """Test that jac create --cl + jac run doesn't create files outside .jac/ directory."""
757
+ test_project_name = "test-cl-no-root-files"
758
+
759
+ with tempfile.TemporaryDirectory() as temp_dir:
760
+ original_cwd = os.getcwd()
761
+ try:
762
+ os.chdir(temp_dir)
763
+
764
+ # Run jac create --cl command
765
+ process = Popen(
766
+ ["jac", "create", "--cl", test_project_name],
767
+ stdin=PIPE,
768
+ stdout=PIPE,
769
+ stderr=PIPE,
770
+ text=True,
771
+ )
772
+ stdout, stderr = process.communicate()
773
+ assert process.returncode == 0, f"jac create --cl failed: {stderr}"
774
+
775
+ project_path = os.path.join(temp_dir, test_project_name)
776
+
777
+ # Record files after create (before run), excluding .jac directory
778
+ def get_root_files(path: str) -> set[str]:
779
+ """Get files/dirs in project root, excluding .jac directory."""
780
+ items = set()
781
+ for item in os.listdir(path):
782
+ if item != ".jac":
783
+ items.add(item)
784
+ return items
785
+
786
+ files_before_run = get_root_files(project_path)
787
+
788
+ # Run jac run main.jac
789
+ process = Popen(
790
+ ["jac", "run", "main.jac"],
791
+ cwd=project_path,
792
+ stdin=PIPE,
793
+ stdout=PIPE,
794
+ stderr=PIPE,
795
+ text=True,
796
+ )
797
+ stdout, stderr = process.communicate()
798
+ assert process.returncode == 0, f"jac run failed: {stderr}"
799
+
800
+ # Record files after run
801
+ files_after_run = get_root_files(project_path)
802
+
803
+ # Check no new files were created in project root
804
+ new_files = files_after_run - files_before_run
805
+ assert not new_files, (
806
+ f"jac run created unexpected files in project root: {new_files}. "
807
+ "All runtime files should be in .jac/ directory."
808
+ )
809
+
810
+ finally:
811
+ os.chdir(original_cwd)