jac-client 0.1.0__py3-none-any.whl → 0.2.1__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 +232 -172
- jac_client/docs/advanced-state.md +1012 -452
- jac_client/docs/asset-serving/intro.md +209 -0
- jac_client/docs/assets/pipe_line-v2.svg +32 -0
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/intro.md +90 -0
- jac_client/docs/guide-example/intro.md +117 -0
- jac_client/docs/guide-example/step-01-setup.md +260 -0
- jac_client/docs/guide-example/step-02-components.md +416 -0
- jac_client/docs/guide-example/step-03-styling.md +478 -0
- jac_client/docs/guide-example/step-04-todo-ui.md +477 -0
- jac_client/docs/guide-example/step-05-local-state.md +530 -0
- jac_client/docs/guide-example/step-06-events.md +750 -0
- jac_client/docs/guide-example/step-07-effects.md +469 -0
- jac_client/docs/guide-example/step-08-walkers.md +534 -0
- jac_client/docs/guide-example/step-09-authentication.md +586 -0
- jac_client/docs/guide-example/step-10-routing.md +540 -0
- jac_client/docs/guide-example/step-11-final.md +964 -0
- jac_client/docs/imports.md +538 -46
- jac_client/docs/lifecycle-hooks.md +517 -297
- jac_client/docs/routing.md +487 -357
- jac_client/docs/styling/intro.md +250 -0
- jac_client/docs/styling/js-styling.md +373 -0
- jac_client/docs/styling/material-ui.md +346 -0
- jac_client/docs/styling/pure-css.md +305 -0
- jac_client/docs/styling/sass.md +409 -0
- jac_client/docs/styling/styled-components.md +401 -0
- jac_client/docs/styling/tailwind.md +303 -0
- jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
- jac_client/examples/asset-serving/css-with-image/README.md +91 -0
- jac_client/examples/asset-serving/css-with-image/app.jac +67 -0
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +28 -0
- jac_client/examples/asset-serving/css-with-image/styles.css +27 -0
- jac_client/examples/asset-serving/css-with-image/vite.config.js +29 -0
- jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
- jac_client/examples/asset-serving/image-asset/README.md +119 -0
- jac_client/examples/asset-serving/image-asset/app.jac +43 -0
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +28 -0
- jac_client/examples/asset-serving/image-asset/styles.css +27 -0
- jac_client/examples/asset-serving/image-asset/vite.config.js +29 -0
- jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
- jac_client/examples/asset-serving/import-alias/README.md +83 -0
- jac_client/examples/asset-serving/import-alias/app.jac +57 -0
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +28 -0
- jac_client/examples/asset-serving/import-alias/vite.config.js +29 -0
- jac_client/examples/basic/.babelrc +9 -0
- jac_client/examples/basic/README.md +16 -0
- jac_client/examples/basic/app.jac +16 -0
- jac_client/examples/basic/package.json +27 -0
- jac_client/examples/basic/vite.config.js +28 -0
- jac_client/examples/basic-auth/.babelrc +9 -0
- jac_client/examples/basic-auth/README.md +16 -0
- jac_client/examples/basic-auth/app.jac +308 -0
- jac_client/examples/basic-auth/package.json +27 -0
- jac_client/examples/basic-auth/vite.config.js +28 -0
- jac_client/examples/basic-auth-with-router/.babelrc +9 -0
- jac_client/examples/basic-auth-with-router/README.md +60 -0
- jac_client/examples/basic-auth-with-router/app.jac +464 -0
- jac_client/examples/basic-auth-with-router/package.json +28 -0
- jac_client/examples/basic-auth-with-router/vite.config.js +28 -0
- jac_client/examples/basic-full-stack/.babelrc +9 -0
- jac_client/examples/basic-full-stack/README.md +18 -0
- jac_client/examples/basic-full-stack/app.jac +320 -0
- jac_client/examples/basic-full-stack/package.json +28 -0
- jac_client/examples/basic-full-stack/vite.config.js +28 -0
- jac_client/examples/css-styling/js-styling/.babelrc +9 -0
- jac_client/examples/css-styling/js-styling/README.md +183 -0
- jac_client/examples/css-styling/js-styling/app.jac +63 -0
- jac_client/examples/css-styling/js-styling/package.json +28 -0
- jac_client/examples/css-styling/js-styling/styles.js +100 -0
- jac_client/examples/css-styling/js-styling/vite.config.js +28 -0
- jac_client/examples/css-styling/material-ui/.babelrc +9 -0
- jac_client/examples/css-styling/material-ui/README.md +16 -0
- jac_client/examples/css-styling/material-ui/app.jac +82 -0
- jac_client/examples/css-styling/material-ui/package.json +32 -0
- jac_client/examples/css-styling/material-ui/vite.config.js +28 -0
- jac_client/examples/css-styling/pure-css/.babelrc +9 -0
- jac_client/examples/css-styling/pure-css/README.md +16 -0
- jac_client/examples/css-styling/pure-css/app.jac +63 -0
- jac_client/examples/css-styling/pure-css/package.json +28 -0
- jac_client/examples/css-styling/pure-css/styles.css +112 -0
- jac_client/examples/css-styling/pure-css/vite.config.js +28 -0
- jac_client/examples/css-styling/sass-example/.babelrc +9 -0
- jac_client/examples/css-styling/sass-example/README.md +16 -0
- jac_client/examples/css-styling/sass-example/app.jac +63 -0
- jac_client/examples/css-styling/sass-example/package.json +29 -0
- jac_client/examples/css-styling/sass-example/styles.scss +158 -0
- jac_client/examples/css-styling/sass-example/vite.config.js +28 -0
- jac_client/examples/css-styling/styled-components/.babelrc +9 -0
- jac_client/examples/css-styling/styled-components/README.md +16 -0
- jac_client/examples/css-styling/styled-components/app.jac +66 -0
- jac_client/examples/css-styling/styled-components/package.json +29 -0
- jac_client/examples/css-styling/styled-components/styled.js +91 -0
- jac_client/examples/css-styling/styled-components/vite.config.js +28 -0
- jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
- jac_client/examples/css-styling/tailwind-example/README.md +16 -0
- jac_client/examples/css-styling/tailwind-example/app.jac +64 -0
- jac_client/examples/css-styling/tailwind-example/global.css +1 -0
- jac_client/examples/css-styling/tailwind-example/package.json +30 -0
- jac_client/examples/css-styling/tailwind-example/vite.config.js +30 -0
- jac_client/examples/full-stack-with-auth/.babelrc +9 -0
- jac_client/examples/full-stack-with-auth/README.md +16 -0
- jac_client/examples/full-stack-with-auth/app.jac +735 -0
- jac_client/examples/full-stack-with-auth/package.json +28 -0
- jac_client/examples/full-stack-with-auth/vite.config.js +30 -0
- jac_client/examples/with-router/.babelrc +9 -0
- jac_client/examples/with-router/README.md +17 -0
- jac_client/examples/with-router/app.jac +323 -0
- jac_client/examples/with-router/package.json +28 -0
- jac_client/examples/with-router/vite.config.js +28 -0
- jac_client/plugin/cli.py +95 -179
- jac_client/plugin/client.py +111 -2
- jac_client/plugin/client_runtime.jac +183 -890
- jac_client/plugin/vite_client_bundle.py +185 -205
- jac_client/tests/__init__.py +0 -1
- jac_client/tests/fixtures/{client_app.jac → basic-app/app.jac} +1 -1
- jac_client/tests/fixtures/cl_file/app.cl.jac +38 -0
- jac_client/tests/fixtures/cl_file/app.jac +15 -0
- jac_client/tests/fixtures/{client_app_with_antd.jac → client_app_with_antd/app.jac} +7 -0
- jac_client/tests/fixtures/{js_import.jac → js_import/app.jac} +2 -2
- jac_client/tests/fixtures/{relative_import.jac → relative_import/app.jac} +1 -1
- jac_client/tests/fixtures/{button.jac → relative_import/button.jac} +2 -2
- jac_client/tests/fixtures/spawn_test/app.jac +133 -0
- jac_client/tests/fixtures/{test_fragments_spread.jac → test_fragments_spread/app.jac} +11 -2
- jac_client/tests/test_asset_examples.py +339 -0
- jac_client/tests/test_cl.py +345 -151
- jac_client/tests/test_create_jac_app.py +41 -45
- {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/METADATA +72 -16
- jac_client-0.2.1.dist-info/RECORD +140 -0
- jac_client/examples/little-x/package-lock.json +0 -2840
- jac_client/examples/todo-app/README.md +0 -82
- jac_client/examples/todo-app/app.jac +0 -683
- jac_client/examples/todo-app/package-lock.json +0 -999
- jac_client/examples/todo-app/package.json +0 -22
- jac_client-0.1.0.dist-info/RECORD +0 -33
- /jac_client/tests/fixtures/{utils.js → js_import/utils.js} +0 -0
- {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/WHEEL +0 -0
- {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/entry_points.txt +0 -0
jac_client/plugin/cli.py
CHANGED
|
@@ -77,12 +77,16 @@ class JacCmd:
|
|
|
77
77
|
package_data = json.load(f)
|
|
78
78
|
|
|
79
79
|
# create temp folder
|
|
80
|
-
|
|
81
|
-
os.makedirs(
|
|
80
|
+
src_folder = os.path.join(project_path, "src")
|
|
81
|
+
os.makedirs(src_folder, exist_ok=True)
|
|
82
82
|
|
|
83
|
-
# create
|
|
84
|
-
|
|
85
|
-
os.makedirs(
|
|
83
|
+
# create build folder
|
|
84
|
+
build_folder = os.path.join(project_path, "build")
|
|
85
|
+
os.makedirs(build_folder, exist_ok=True)
|
|
86
|
+
|
|
87
|
+
# create assets folder for static assets (images, fonts, etc.)
|
|
88
|
+
assets_folder = os.path.join(project_path, "assets")
|
|
89
|
+
os.makedirs(assets_folder, exist_ok=True)
|
|
86
90
|
|
|
87
91
|
# Update package.json with Jac-specific configuration
|
|
88
92
|
package_data.update(
|
|
@@ -91,12 +95,23 @@ class JacCmd:
|
|
|
91
95
|
"description": f"Jac application: {name}",
|
|
92
96
|
"type": "module",
|
|
93
97
|
"scripts": {
|
|
94
|
-
"build": "vite build",
|
|
98
|
+
"build": "npm run compile && vite build",
|
|
95
99
|
"dev": "vite dev",
|
|
96
100
|
"preview": "vite preview",
|
|
101
|
+
"compile": 'babel src --out-dir build --extensions ".jsx,.js" --out-file-extension .js',
|
|
102
|
+
},
|
|
103
|
+
"devDependencies": {
|
|
104
|
+
"vite": "^6.4.1",
|
|
105
|
+
"@babel/cli": "^7.28.3",
|
|
106
|
+
"@babel/core": "^7.28.5",
|
|
107
|
+
"@babel/preset-env": "^7.28.5",
|
|
108
|
+
"@babel/preset-react": "^7.28.5",
|
|
109
|
+
},
|
|
110
|
+
"dependencies": {
|
|
111
|
+
"react": "^19.2.0",
|
|
112
|
+
"react-dom": "^19.2.0",
|
|
113
|
+
"react-router-dom": "^6.30.1",
|
|
97
114
|
},
|
|
98
|
-
"devDependencies": {"vite": "^5.0.0"},
|
|
99
|
-
"dependencies": {"react": "^18.2.0", "react-dom": "^18.2.0"},
|
|
100
115
|
}
|
|
101
116
|
)
|
|
102
117
|
|
|
@@ -117,190 +132,91 @@ class JacCmd:
|
|
|
117
132
|
# Create a basic Jac file
|
|
118
133
|
main_jac_content = """
|
|
119
134
|
# Pages
|
|
120
|
-
cl
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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>;
|
|
135
|
+
cl import from react {useState, useEffect}
|
|
136
|
+
cl {
|
|
137
|
+
def app() -> any {
|
|
138
|
+
let [count, setCount] = useState(0);
|
|
139
|
+
useEffect(lambda -> None {
|
|
140
|
+
console.log("Count: ", count);
|
|
141
|
+
}, [count]);
|
|
142
|
+
return <div>
|
|
143
|
+
<h1>Hello, World!</h1>
|
|
144
|
+
<p>Count: {count}</p>
|
|
145
|
+
<button onClick={lambda e: any -> None {setCount(count + 1);}}>Increment</button>
|
|
146
|
+
</div>;
|
|
147
|
+
}
|
|
261
148
|
}
|
|
149
|
+
"""
|
|
262
150
|
|
|
151
|
+
with open(os.path.join(project_path, "app.jac"), "w") as f:
|
|
152
|
+
f.write(main_jac_content)
|
|
263
153
|
|
|
264
|
-
#
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
"
|
|
269
|
-
|
|
270
|
-
|
|
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();
|
|
154
|
+
# create .babelrc file
|
|
155
|
+
babel_config_content = """
|
|
156
|
+
{
|
|
157
|
+
"presets": [[
|
|
158
|
+
"@babel/preset-env",
|
|
159
|
+
{
|
|
160
|
+
"modules": false
|
|
161
|
+
}
|
|
162
|
+
], "@babel/preset-react"]
|
|
285
163
|
}
|
|
286
164
|
"""
|
|
165
|
+
with open(os.path.join(project_path, ".babelrc"), "w") as f:
|
|
166
|
+
f.write(babel_config_content)
|
|
167
|
+
|
|
168
|
+
# create vite.config.js file
|
|
169
|
+
vite_config_content = """
|
|
170
|
+
import { defineConfig } from "vite";
|
|
171
|
+
import path from "path";
|
|
172
|
+
import { fileURLToPath } from "url";
|
|
173
|
+
|
|
174
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
175
|
+
|
|
176
|
+
export default defineConfig({
|
|
177
|
+
root: ".", // base folder
|
|
178
|
+
build: {
|
|
179
|
+
rollupOptions: {
|
|
180
|
+
input: "build/main.js", // your compiled entry file
|
|
181
|
+
output: {
|
|
182
|
+
entryFileNames: "client.[hash].js", // name of the final js file
|
|
183
|
+
assetFileNames: "[name].[ext]",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
outDir: "dist", // final bundled output
|
|
187
|
+
emptyOutDir: true,
|
|
188
|
+
},
|
|
189
|
+
publicDir: false,
|
|
190
|
+
resolve: {
|
|
191
|
+
alias: {
|
|
192
|
+
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
193
|
+
"@jac-client/assets": path.resolve(__dirname, "src/assets"),
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
287
197
|
|
|
288
|
-
|
|
289
|
-
|
|
198
|
+
"""
|
|
199
|
+
with open(os.path.join(project_path, "vite.config.js"), "w") as f:
|
|
200
|
+
f.write(vite_config_content)
|
|
290
201
|
|
|
291
202
|
# Create README.md
|
|
292
203
|
readme_content = f"""# {name}
|
|
293
204
|
|
|
294
|
-
|
|
205
|
+
## Running Jac Code
|
|
295
206
|
|
|
296
|
-
|
|
207
|
+
make sure node modules are installed:
|
|
208
|
+
```bash
|
|
209
|
+
npm install
|
|
210
|
+
```
|
|
297
211
|
|
|
298
|
-
|
|
299
|
-
jac serve app.jac
|
|
300
|
-
```
|
|
212
|
+
To run your Jac code, use the Jac CLI:
|
|
301
213
|
|
|
302
|
-
|
|
303
|
-
|
|
214
|
+
```bash
|
|
215
|
+
jac serve app.jac
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Happy coding with Jac!
|
|
219
|
+
"""
|
|
304
220
|
|
|
305
221
|
with open(os.path.join(project_path, "README.md"), "w") as f:
|
|
306
222
|
f.write(readme_content)
|
jac_client/plugin/client.py
CHANGED
|
@@ -1,14 +1,79 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import html
|
|
3
|
+
import mimetypes
|
|
1
4
|
import types
|
|
5
|
+
from http.server import BaseHTTPRequestHandler
|
|
2
6
|
from pathlib import Path
|
|
7
|
+
from typing import Any, Literal, TypeAlias
|
|
3
8
|
|
|
4
9
|
from jaclang.runtimelib.client_bundle import ClientBundle
|
|
5
10
|
from jaclang.runtimelib.machine import (
|
|
6
11
|
JacMachine as Jac,
|
|
7
12
|
hookimpl,
|
|
8
13
|
)
|
|
14
|
+
from jaclang.runtimelib.server import ModuleIntrospector
|
|
9
15
|
|
|
10
16
|
from .vite_client_bundle import ViteClientBundleBuilder
|
|
11
17
|
|
|
18
|
+
JsonValue: TypeAlias = (
|
|
19
|
+
None | str | int | float | bool | list["JsonValue"] | dict[str, "JsonValue"]
|
|
20
|
+
)
|
|
21
|
+
StatusCode: TypeAlias = Literal[200, 201, 400, 401, 404, 503]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class JacClientModuleIntrospector(ModuleIntrospector):
|
|
25
|
+
"""Jac Client Module Introspector."""
|
|
26
|
+
|
|
27
|
+
def render_page(
|
|
28
|
+
self, function_name: str, args: dict[str, Any], username: str
|
|
29
|
+
) -> dict[str, Any]:
|
|
30
|
+
"""Render HTML page for client function using the Vite bundle."""
|
|
31
|
+
self.load()
|
|
32
|
+
|
|
33
|
+
available_exports = set(self._client_manifest.get("exports", [])) or set(
|
|
34
|
+
self.get_client_functions().keys()
|
|
35
|
+
)
|
|
36
|
+
if function_name not in available_exports:
|
|
37
|
+
raise ValueError(f"Client function '{function_name}' not found")
|
|
38
|
+
|
|
39
|
+
bundle_hash = self.ensure_bundle()
|
|
40
|
+
|
|
41
|
+
# Find CSS file in dist directory
|
|
42
|
+
base_path = Path(Jac.base_path_dir)
|
|
43
|
+
dist_dir = base_path / "dist"
|
|
44
|
+
css_link = ""
|
|
45
|
+
|
|
46
|
+
# Try to find CSS file (main.css is the default Vite output)
|
|
47
|
+
css_file = dist_dir / "main.css"
|
|
48
|
+
if css_file.exists():
|
|
49
|
+
css_hash = hashlib.sha256(css_file.read_bytes()).hexdigest()[:8]
|
|
50
|
+
css_link = (
|
|
51
|
+
f'<link rel="stylesheet" href="/static/main.css?hash={css_hash}"/>'
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
head_content = f'<meta charset="utf-8"/>\n <title>{html.escape(function_name)}</title>'
|
|
55
|
+
if css_link:
|
|
56
|
+
head_content += f"\n {css_link}"
|
|
57
|
+
|
|
58
|
+
page = (
|
|
59
|
+
"<!DOCTYPE html>"
|
|
60
|
+
'<html lang="en">'
|
|
61
|
+
"<head>"
|
|
62
|
+
f"{head_content}"
|
|
63
|
+
"</head>"
|
|
64
|
+
"<body>"
|
|
65
|
+
'<div id="root"></div>'
|
|
66
|
+
f'<script src="/static/client.js?hash={bundle_hash}" defer></script>'
|
|
67
|
+
"</body>"
|
|
68
|
+
"</html>"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
"html": page,
|
|
73
|
+
"bundle_hash": bundle_hash,
|
|
74
|
+
"bundle_code": self._bundle.code,
|
|
75
|
+
}
|
|
76
|
+
|
|
12
77
|
|
|
13
78
|
class JacClient:
|
|
14
79
|
"""Jac Client."""
|
|
@@ -19,10 +84,9 @@ class JacClient:
|
|
|
19
84
|
"""Get the client bundle builder instance."""
|
|
20
85
|
base_path = Path(Jac.base_path_dir)
|
|
21
86
|
package_json_path = base_path / "package.json"
|
|
22
|
-
output_dir = base_path / "
|
|
87
|
+
output_dir = base_path / "dist"
|
|
23
88
|
# Use the plugin's client_runtime.jac file
|
|
24
89
|
runtime_path = Path(__file__).with_name("client_runtime.jac")
|
|
25
|
-
print(f"Runtime path: {runtime_path}")
|
|
26
90
|
return ViteClientBundleBuilder(
|
|
27
91
|
runtime_path=runtime_path,
|
|
28
92
|
vite_package_json=package_json_path,
|
|
@@ -39,3 +103,48 @@ class JacClient:
|
|
|
39
103
|
"""Build a client bundle for the supplied module."""
|
|
40
104
|
builder = JacClient.get_client_bundle_builder()
|
|
41
105
|
return builder.build(module, force=force)
|
|
106
|
+
|
|
107
|
+
@staticmethod
|
|
108
|
+
@hookimpl
|
|
109
|
+
def get_module_introspector(
|
|
110
|
+
module_name: str, base_path: str | None
|
|
111
|
+
) -> ModuleIntrospector:
|
|
112
|
+
"""Get a module introspector for the supplied module."""
|
|
113
|
+
return JacClientModuleIntrospector(module_name, base_path)
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
@hookimpl
|
|
117
|
+
def send_static_file(
|
|
118
|
+
handler: BaseHTTPRequestHandler,
|
|
119
|
+
file_path: Path,
|
|
120
|
+
content_type: str | None = None,
|
|
121
|
+
) -> None:
|
|
122
|
+
"""Send static file response (images, fonts, etc.).
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
handler: HTTP request handler
|
|
126
|
+
file_path: Path to the file to serve
|
|
127
|
+
content_type: MIME type (auto-detected if None)
|
|
128
|
+
"""
|
|
129
|
+
from jaclang.runtimelib.server import ResponseBuilder
|
|
130
|
+
|
|
131
|
+
if not file_path.exists() or not file_path.is_file():
|
|
132
|
+
ResponseBuilder.send_json(handler, 404, {"error": "File not found"})
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
file_content = file_path.read_bytes()
|
|
137
|
+
if content_type is None:
|
|
138
|
+
content_type, _ = mimetypes.guess_type(str(file_path))
|
|
139
|
+
if content_type is None:
|
|
140
|
+
content_type = "application/octet-stream"
|
|
141
|
+
|
|
142
|
+
handler.send_response(200)
|
|
143
|
+
handler.send_header("Content-Type", content_type)
|
|
144
|
+
handler.send_header("Content-Length", str(len(file_content)))
|
|
145
|
+
handler.send_header("Cache-Control", "public, max-age=3600")
|
|
146
|
+
ResponseBuilder._add_cors_headers(handler)
|
|
147
|
+
handler.end_headers()
|
|
148
|
+
handler.wfile.write(file_content)
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
ResponseBuilder.send_json(handler, 500, {"error": str(exc)})
|