jac-client 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- jac_client/tests/conftest.py +281 -0
- jac_client/tests/test_cli.py +755 -0
- jac_client/tests/test_it.py +347 -67
- {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/METADATA +28 -30
- jac_client-0.2.4.dist-info/RECORD +10 -0
- {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/WHEEL +2 -1
- jac_client-0.2.4.dist-info/entry_points.txt +4 -0
- jac_client-0.2.4.dist-info/top_level.txt +1 -0
- jac_client/docs/README.md +0 -689
- jac_client/docs/advanced-state.md +0 -1265
- jac_client/docs/asset-serving/intro.md +0 -209
- jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/app.jac.md +0 -121
- jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client/docs/file-system/intro.md +0 -72
- jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client/docs/guide-example/intro.md +0 -115
- jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client/docs/imports.md +0 -1141
- jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client/docs/routing.md +0 -659
- jac_client/docs/styling/intro.md +0 -249
- jac_client/docs/styling/js-styling.md +0 -367
- jac_client/docs/styling/material-ui.md +0 -341
- jac_client/docs/styling/pure-css.md +0 -299
- jac_client/docs/styling/sass.md +0 -403
- jac_client/docs/styling/styled-components.md +0 -395
- jac_client/docs/styling/tailwind.md +0 -298
- jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client/examples/all-in-one/README.md +0 -16
- jac_client/examples/all-in-one/app.jac +0 -426
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/button.jac +0 -7
- jac_client/examples/all-in-one/components/button.jac +0 -7
- jac_client/examples/all-in-one/package.json +0 -29
- jac_client/examples/all-in-one/styles.css +0 -26
- jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client/examples/asset-serving/css-with-image/app.jac +0 -88
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client/examples/asset-serving/image-asset/app.jac +0 -55
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client/examples/asset-serving/import-alias/app.jac +0 -111
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client/examples/basic/.babelrc +0 -9
- jac_client/examples/basic/README.md +0 -16
- jac_client/examples/basic/app.jac +0 -21
- jac_client/examples/basic/package.json +0 -27
- jac_client/examples/basic/vite.config.js +0 -27
- jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client/examples/basic-auth/README.md +0 -16
- jac_client/examples/basic-auth/app.jac +0 -308
- jac_client/examples/basic-auth/package.json +0 -27
- jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client/examples/basic-auth-with-router/app.jac +0 -464
- jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client/examples/basic-full-stack/app.jac +0 -320
- jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client/examples/css-styling/js-styling/app.jac +0 -84
- jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client/examples/css-styling/material-ui/app.jac +0 -122
- jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client/examples/css-styling/pure-css/app.jac +0 -64
- jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client/examples/css-styling/sass-example/app.jac +0 -64
- jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client/examples/css-styling/styled-components/app.jac +0 -71
- jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client/examples/css-styling/tailwind-example/app.jac +0 -63
- jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client/examples/full-stack-with-auth/app.jac +0 -722
- jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client/examples/little-x/app.jac +0 -724
- jac_client/examples/little-x/package.json +0 -23
- jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +0 -11
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/app.jac +0 -35
- jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +0 -19
- jac_client/examples/nested-folders/nested-advance/level1/Card.jac +0 -43
- jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +0 -25
- jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client/examples/nested-folders/nested-basic/app.jac +0 -13
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/button.jac +0 -7
- jac_client/examples/nested-folders/nested-basic/components/button.jac +0 -7
- jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client/examples/with-router/.babelrc +0 -9
- jac_client/examples/with-router/README.md +0 -17
- jac_client/examples/with-router/app.jac +0 -323
- jac_client/examples/with-router/package.json +0 -28
- jac_client/examples/with-router/vite.config.js +0 -27
- jac_client/plugin/cli.py +0 -244
- jac_client/plugin/client.py +0 -152
- jac_client/plugin/client_runtime.jac +0 -234
- jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client/tests/fixtures/basic-app/app.jac +0 -23
- jac_client/tests/fixtures/cl_file/app.cl.jac +0 -48
- jac_client/tests/fixtures/cl_file/app.jac +0 -15
- jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -34
- jac_client/tests/fixtures/js_import/app.jac +0 -34
- jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client/tests/fixtures/package.json +0 -11
- jac_client/tests/fixtures/relative_import/app.jac +0 -11
- jac_client/tests/fixtures/relative_import/button.jac +0 -7
- jac_client/tests/fixtures/spawn_test/app.jac +0 -129
- jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -67
- jac_client/tests/test_asset_examples.py +0 -322
- jac_client/tests/test_cl.py +0 -530
- jac_client/tests/test_create_jac_app.py +0 -131
- jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.3.dist-info/RECORD +0 -171
- jac_client-0.2.3.dist-info/entry_points.txt +0 -4
jac_client/plugin/client.py
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import hashlib
|
|
2
|
-
import html
|
|
3
|
-
import mimetypes
|
|
4
|
-
import types
|
|
5
|
-
from http.server import BaseHTTPRequestHandler
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
from typing import Any, Literal, TypeAlias
|
|
8
|
-
|
|
9
|
-
from jaclang.runtimelib.client_bundle import ClientBundle
|
|
10
|
-
from jaclang.runtimelib.runtime import (
|
|
11
|
-
JacRuntime as Jac,
|
|
12
|
-
)
|
|
13
|
-
from jaclang.runtimelib.runtime import (
|
|
14
|
-
hookimpl,
|
|
15
|
-
)
|
|
16
|
-
from jaclang.runtimelib.server import ModuleIntrospector
|
|
17
|
-
|
|
18
|
-
from .vite_client_bundle import ViteClientBundleBuilder
|
|
19
|
-
|
|
20
|
-
JsonValue: TypeAlias = (
|
|
21
|
-
None | str | int | float | bool | list["JsonValue"] | dict[str, "JsonValue"]
|
|
22
|
-
)
|
|
23
|
-
StatusCode: TypeAlias = Literal[200, 201, 400, 401, 404, 503]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class JacClientModuleIntrospector(ModuleIntrospector):
|
|
27
|
-
"""Jac Client Module Introspector."""
|
|
28
|
-
|
|
29
|
-
def render_page(
|
|
30
|
-
self, function_name: str, args: dict[str, Any], username: str
|
|
31
|
-
) -> dict[str, Any]:
|
|
32
|
-
"""Render HTML page for client function using the Vite bundle."""
|
|
33
|
-
self.load()
|
|
34
|
-
|
|
35
|
-
available_exports = set(self._client_manifest.get("exports", [])) or set(
|
|
36
|
-
self.get_client_functions().keys()
|
|
37
|
-
)
|
|
38
|
-
if function_name not in available_exports:
|
|
39
|
-
raise ValueError(f"Client function '{function_name}' not found")
|
|
40
|
-
|
|
41
|
-
bundle_hash = self.ensure_bundle()
|
|
42
|
-
|
|
43
|
-
# Find CSS file in dist directory
|
|
44
|
-
base_path = Path(Jac.base_path_dir)
|
|
45
|
-
dist_dir = base_path / "dist"
|
|
46
|
-
css_link = ""
|
|
47
|
-
|
|
48
|
-
# Try to find CSS file (main.css is the default Vite output)
|
|
49
|
-
css_file = dist_dir / "main.css"
|
|
50
|
-
if css_file.exists():
|
|
51
|
-
css_hash = hashlib.sha256(css_file.read_bytes()).hexdigest()[:8]
|
|
52
|
-
css_link = (
|
|
53
|
-
f'<link rel="stylesheet" href="/static/main.css?hash={css_hash}"/>'
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
head_content = f'<meta charset="utf-8"/>\n <title>{html.escape(function_name)}</title>'
|
|
57
|
-
if css_link:
|
|
58
|
-
head_content += f"\n {css_link}"
|
|
59
|
-
|
|
60
|
-
page = (
|
|
61
|
-
"<!DOCTYPE html>"
|
|
62
|
-
'<html lang="en">'
|
|
63
|
-
"<head>"
|
|
64
|
-
f"{head_content}"
|
|
65
|
-
"</head>"
|
|
66
|
-
"<body>"
|
|
67
|
-
'<div id="root"></div>'
|
|
68
|
-
f'<script src="/static/client.js?hash={bundle_hash}" defer></script>'
|
|
69
|
-
"</body>"
|
|
70
|
-
"</html>"
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
"html": page,
|
|
75
|
-
"bundle_hash": bundle_hash,
|
|
76
|
-
"bundle_code": self._bundle.code,
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
class JacClient:
|
|
81
|
-
"""Jac Client."""
|
|
82
|
-
|
|
83
|
-
@staticmethod
|
|
84
|
-
@hookimpl
|
|
85
|
-
def get_client_bundle_builder() -> ViteClientBundleBuilder:
|
|
86
|
-
"""Get the client bundle builder instance."""
|
|
87
|
-
base_path = Path(Jac.base_path_dir)
|
|
88
|
-
package_json_path = base_path / "package.json"
|
|
89
|
-
output_dir = base_path / "dist"
|
|
90
|
-
# Use the plugin's client_runtime.jac file
|
|
91
|
-
runtime_path = Path(__file__).with_name("client_runtime.jac")
|
|
92
|
-
return ViteClientBundleBuilder(
|
|
93
|
-
runtime_path=runtime_path,
|
|
94
|
-
vite_package_json=package_json_path,
|
|
95
|
-
vite_output_dir=output_dir,
|
|
96
|
-
vite_minify=False,
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
@staticmethod
|
|
100
|
-
@hookimpl
|
|
101
|
-
def build_client_bundle(
|
|
102
|
-
module: types.ModuleType,
|
|
103
|
-
force: bool = False,
|
|
104
|
-
) -> ClientBundle:
|
|
105
|
-
"""Build a client bundle for the supplied module."""
|
|
106
|
-
builder = JacClient.get_client_bundle_builder()
|
|
107
|
-
return builder.build(module, force=force)
|
|
108
|
-
|
|
109
|
-
@staticmethod
|
|
110
|
-
@hookimpl
|
|
111
|
-
def get_module_introspector(
|
|
112
|
-
module_name: str, base_path: str | None
|
|
113
|
-
) -> ModuleIntrospector:
|
|
114
|
-
"""Get a module introspector for the supplied module."""
|
|
115
|
-
return JacClientModuleIntrospector(module_name, base_path)
|
|
116
|
-
|
|
117
|
-
@staticmethod
|
|
118
|
-
@hookimpl
|
|
119
|
-
def send_static_file(
|
|
120
|
-
handler: BaseHTTPRequestHandler,
|
|
121
|
-
file_path: Path,
|
|
122
|
-
content_type: str | None = None,
|
|
123
|
-
) -> None:
|
|
124
|
-
"""Send static file response (images, fonts, etc.).
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
handler: HTTP request handler
|
|
128
|
-
file_path: Path to the file to serve
|
|
129
|
-
content_type: MIME type (auto-detected if None)
|
|
130
|
-
"""
|
|
131
|
-
from jaclang.runtimelib.server import ResponseBuilder
|
|
132
|
-
|
|
133
|
-
if not file_path.exists() or not file_path.is_file():
|
|
134
|
-
ResponseBuilder.send_json(handler, 404, {"error": "File not found"})
|
|
135
|
-
return
|
|
136
|
-
|
|
137
|
-
try:
|
|
138
|
-
file_content = file_path.read_bytes()
|
|
139
|
-
if content_type is None:
|
|
140
|
-
content_type, _ = mimetypes.guess_type(str(file_path))
|
|
141
|
-
if content_type is None:
|
|
142
|
-
content_type = "application/octet-stream"
|
|
143
|
-
|
|
144
|
-
handler.send_response(200)
|
|
145
|
-
handler.send_header("Content-Type", content_type)
|
|
146
|
-
handler.send_header("Content-Length", str(len(file_content)))
|
|
147
|
-
handler.send_header("Cache-Control", "public, max-age=3600")
|
|
148
|
-
ResponseBuilder._add_cors_headers(handler)
|
|
149
|
-
handler.end_headers()
|
|
150
|
-
handler.wfile.write(file_content)
|
|
151
|
-
except Exception as exc:
|
|
152
|
-
ResponseBuilder.send_json(handler, 500, {"error": str(exc)})
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
"""Client-side runtime for Jac JSX and walker interactions."""
|
|
2
|
-
|
|
3
|
-
cl import from 'react' { * as React }
|
|
4
|
-
cl import from 'react-dom/client' { * as ReactDOM }
|
|
5
|
-
cl 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
|
-
cl {
|
|
17
|
-
# JSX factory function - uses React.createElement
|
|
18
|
-
def __jacJsx(tag: any, props: dict = {}, children: any = []) -> any {
|
|
19
|
-
# Handle fragments: when tag is None/null, use React.Fragment
|
|
20
|
-
if tag == None {
|
|
21
|
-
tag = React.Fragment;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
childrenArray = [];
|
|
25
|
-
if children != None {
|
|
26
|
-
if Array.isArray(children) {
|
|
27
|
-
childrenArray = children;
|
|
28
|
-
} else {
|
|
29
|
-
childrenArray = [children];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
# Filter out null/undefined children
|
|
34
|
-
reactChildren = [];
|
|
35
|
-
for child in childrenArray {
|
|
36
|
-
if child != None {
|
|
37
|
-
reactChildren.push(child);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if reactChildren.length > 0 {
|
|
42
|
-
args = [tag, props];
|
|
43
|
-
for child in reactChildren {
|
|
44
|
-
args.push(child);
|
|
45
|
-
}
|
|
46
|
-
return React.createElement.apply(React, args);
|
|
47
|
-
} else {
|
|
48
|
-
return React.createElement(tag, props);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
# ============================================================================
|
|
53
|
-
# React Router Integration (using react-router-dom v6)
|
|
54
|
-
# ============================================================================
|
|
55
|
-
# Direct re-exports of React Router components for seamless integration
|
|
56
|
-
# Router uses HashRouter for hash-based routing (#/path)
|
|
57
|
-
# See: https://reactrouter.com/6.30.1/router-components/hash-router
|
|
58
|
-
let Router = ReactRouterHashRouter;
|
|
59
|
-
let Routes = ReactRouterRoutes;
|
|
60
|
-
let Route = ReactRouterRoute;
|
|
61
|
-
let Link = ReactRouterLink;
|
|
62
|
-
let Navigate = ReactRouterNavigate;
|
|
63
|
-
|
|
64
|
-
# React Router Hooks - wrapped for Jac compatibility
|
|
65
|
-
let useNavigate = reactRouterUseNavigate;
|
|
66
|
-
let useLocation = reactRouterUseLocation;
|
|
67
|
-
let useParams = reactRouterUseParams;
|
|
68
|
-
|
|
69
|
-
# useRouter Hook - convenience hook that combines common router utilities
|
|
70
|
-
def useRouter() -> dict {
|
|
71
|
-
navigate = reactRouterUseNavigate();
|
|
72
|
-
location = reactRouterUseLocation();
|
|
73
|
-
params = reactRouterUseParams();
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
"navigate": navigate,
|
|
77
|
-
"location": location,
|
|
78
|
-
"params": params,
|
|
79
|
-
"pathname": location.pathname,
|
|
80
|
-
"search": location.search,
|
|
81
|
-
"hash": location.hash
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
# navigate function - programmatic navigation (backward compatibility)
|
|
86
|
-
# Note: Use useNavigate() hook inside components instead
|
|
87
|
-
def navigate(path: str) -> None {
|
|
88
|
-
window.location.hash = "#" + path;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
# ============================================================================
|
|
92
|
-
# Walker spawn function
|
|
93
|
-
# ============================================================================
|
|
94
|
-
async def __jacSpawn(left: str, right: str = "", fields: dict = {}) -> any {
|
|
95
|
-
token = __getLocalStorage("jac_token");
|
|
96
|
-
url = f"/walker/{left}";
|
|
97
|
-
if right != "" {
|
|
98
|
-
url = f"/walker/{left}/{right}";
|
|
99
|
-
}
|
|
100
|
-
response = await fetch(
|
|
101
|
-
url,
|
|
102
|
-
{
|
|
103
|
-
"method": "POST",
|
|
104
|
-
"accept": "application/json",
|
|
105
|
-
"headers": {
|
|
106
|
-
"Content-Type": "application/json",
|
|
107
|
-
"Authorization": f"Bearer {token}" if token else ""
|
|
108
|
-
},
|
|
109
|
-
"body": JSON.stringify(fields)
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
if not response.ok {
|
|
114
|
-
error_text = await response.json();
|
|
115
|
-
raise Exception(f"Walker {walker} failed: {error_text}") ;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return await response.json();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
def jacSpawn(left: str, right: str = "", fields: dict = {}) -> any {
|
|
122
|
-
return __jacSpawn(left, right, fields);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
# Function call function - calls server-side functions from client
|
|
126
|
-
async def __jacCallFunction(function_name: str, args: dict = {}) -> any {
|
|
127
|
-
token = __getLocalStorage("jac_token");
|
|
128
|
-
|
|
129
|
-
response = await fetch(
|
|
130
|
-
f"/function/{function_name}",
|
|
131
|
-
{
|
|
132
|
-
"method": "POST",
|
|
133
|
-
"headers": {
|
|
134
|
-
"Content-Type": "application/json",
|
|
135
|
-
"Authorization": f"Bearer {token}" if token else ""
|
|
136
|
-
},
|
|
137
|
-
"body": JSON.stringify({"args": args})
|
|
138
|
-
}
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
if not response.ok {
|
|
142
|
-
error_text = await response.text();
|
|
143
|
-
raise Exception(f"Function {function_name} failed: {error_text}") ;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
data = JSON.parse(await response.text());
|
|
147
|
-
return data["result"];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
# Authentication helpers
|
|
151
|
-
async def jacSignup(username: str, password: str) -> dict {
|
|
152
|
-
response = await fetch(
|
|
153
|
-
"/user/create",
|
|
154
|
-
{
|
|
155
|
-
"method": "POST",
|
|
156
|
-
"headers": {"Content-Type": "application/json"},
|
|
157
|
-
"body": JSON.stringify({"username": username, "password": password})
|
|
158
|
-
}
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
if response.ok {
|
|
162
|
-
data = JSON.parse(await response.text());
|
|
163
|
-
token = data["token"];
|
|
164
|
-
if token {
|
|
165
|
-
__setLocalStorage("jac_token", token);
|
|
166
|
-
return {"success": True, "token": token, "username": username};
|
|
167
|
-
}
|
|
168
|
-
return {"success": False, "error": "No token received"};
|
|
169
|
-
} else {
|
|
170
|
-
error_text = await response.text();
|
|
171
|
-
try {
|
|
172
|
-
error_data = JSON.parse(error_text);
|
|
173
|
-
return {
|
|
174
|
-
"success": False,
|
|
175
|
-
"error": error_data["error"]
|
|
176
|
-
if error_data["error"] != None
|
|
177
|
-
else "Signup failed"
|
|
178
|
-
};
|
|
179
|
-
} except Exception {
|
|
180
|
-
return {"success": False, "error": error_text};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async def jacLogin(username: str, password: str) -> bool {
|
|
186
|
-
response = await fetch(
|
|
187
|
-
"/user/login",
|
|
188
|
-
{
|
|
189
|
-
"method": "POST",
|
|
190
|
-
"headers": {"Content-Type": "application/json"},
|
|
191
|
-
"body": JSON.stringify({"username": username, "password": password})
|
|
192
|
-
}
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
if response.ok {
|
|
196
|
-
data = JSON.parse(await response.text());
|
|
197
|
-
token = data["token"];
|
|
198
|
-
if token {
|
|
199
|
-
__setLocalStorage("jac_token", token);
|
|
200
|
-
return True;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return False;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
def jacLogout() -> None {
|
|
207
|
-
__removeLocalStorage("jac_token");
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
def jacIsLoggedIn() -> bool {
|
|
211
|
-
token = __getLocalStorage("jac_token");
|
|
212
|
-
return token != None and token != "";
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
# Browser API shims
|
|
216
|
-
def __getLocalStorage(key: str) -> str {
|
|
217
|
-
storage = globalThis.localStorage;
|
|
218
|
-
return storage.getItem(key) if storage else "";
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
def __setLocalStorage(key: str, value: str) -> None {
|
|
222
|
-
storage = globalThis.localStorage;
|
|
223
|
-
if storage {
|
|
224
|
-
storage.setItem(key, value);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
def __removeLocalStorage(key: str) -> None {
|
|
229
|
-
storage = globalThis.localStorage;
|
|
230
|
-
if storage {
|
|
231
|
-
storage.removeItem(key);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|