jac-client 0.2.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 +659 -0
- jac_client/docs/advanced-state.md +1266 -0
- jac_client/docs/assets/pipe_line.png +0 -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 +1142 -0
- jac_client/docs/lifecycle-hooks.md +774 -0
- jac_client/docs/routing.md +660 -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/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/little-x/app.jac +615 -0
- jac_client/examples/little-x/package.json +23 -0
- jac_client/examples/little-x/submit-button.jac +8 -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 +239 -0
- jac_client/plugin/client.py +89 -0
- jac_client/plugin/client_runtime.jac +234 -0
- jac_client/plugin/vite_client_bundle.py +355 -0
- jac_client/tests/__init__.py +2 -0
- jac_client/tests/fixtures/basic-app/app.jac +18 -0
- jac_client/tests/fixtures/client_app_with_antd/app.jac +28 -0
- jac_client/tests/fixtures/js_import/app.jac +30 -0
- jac_client/tests/fixtures/js_import/utils.js +22 -0
- jac_client/tests/fixtures/package-lock.json +329 -0
- jac_client/tests/fixtures/package.json +11 -0
- jac_client/tests/fixtures/relative_import/app.jac +13 -0
- jac_client/tests/fixtures/relative_import/button.jac +6 -0
- jac_client/tests/fixtures/spawn_test/app.jac +133 -0
- jac_client/tests/fixtures/test_fragments_spread/app.jac +53 -0
- jac_client/tests/test_cl.py +476 -0
- jac_client/tests/test_create_jac_app.py +139 -0
- jac_client-0.2.0.dist-info/METADATA +182 -0
- jac_client-0.2.0.dist-info/RECORD +72 -0
- jac_client-0.2.0.dist-info/WHEEL +4 -0
- jac_client-0.2.0.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
# Simple Authentication App with React Router
|
|
2
|
+
cl import from react {
|
|
3
|
+
useState,
|
|
4
|
+
useEffect
|
|
5
|
+
}
|
|
6
|
+
cl import from "@jac-client/utils" {
|
|
7
|
+
Router,
|
|
8
|
+
Routes,
|
|
9
|
+
Route,
|
|
10
|
+
Link,
|
|
11
|
+
Navigate,
|
|
12
|
+
useNavigate,
|
|
13
|
+
useLocation,
|
|
14
|
+
jacSignup,
|
|
15
|
+
jacLogin,
|
|
16
|
+
jacLogout,
|
|
17
|
+
jacIsLoggedIn
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
cl {
|
|
21
|
+
# Navigation Component
|
|
22
|
+
def Navigation() -> any {
|
|
23
|
+
let isLoggedIn = jacIsLoggedIn();
|
|
24
|
+
let navigate = useNavigate();
|
|
25
|
+
|
|
26
|
+
def handleLogout(e: any) -> None {
|
|
27
|
+
e.preventDefault();
|
|
28
|
+
jacLogout();
|
|
29
|
+
navigate("/login");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if isLoggedIn {
|
|
33
|
+
return <nav
|
|
34
|
+
style={{
|
|
35
|
+
"padding": "16px 24px",
|
|
36
|
+
"background": "#667eea",
|
|
37
|
+
"display": "flex",
|
|
38
|
+
"justifyContent": "space-between",
|
|
39
|
+
"alignItems": "center"
|
|
40
|
+
}}
|
|
41
|
+
>
|
|
42
|
+
<div
|
|
43
|
+
style={{
|
|
44
|
+
"fontSize": "1.25rem",
|
|
45
|
+
"fontWeight": "600",
|
|
46
|
+
"color": "#ffffff"
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
MyApp
|
|
50
|
+
</div>
|
|
51
|
+
<div
|
|
52
|
+
style={{"display": "flex", "gap": "16px"}}
|
|
53
|
+
>
|
|
54
|
+
<Link
|
|
55
|
+
to="/dashboard"
|
|
56
|
+
style={{"color": "#ffffff", "textDecoration": "none"}}
|
|
57
|
+
>
|
|
58
|
+
Dashboard
|
|
59
|
+
</Link>
|
|
60
|
+
<button
|
|
61
|
+
onClick={handleLogout}
|
|
62
|
+
style={{
|
|
63
|
+
"background": "none",
|
|
64
|
+
"color": "#ffffff",
|
|
65
|
+
"border": "1px solid #ffffff",
|
|
66
|
+
"padding": "4px 12px",
|
|
67
|
+
"borderRadius": "4px",
|
|
68
|
+
"cursor": "pointer"
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
Logout
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
</nav>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return <nav
|
|
78
|
+
style={{
|
|
79
|
+
"padding": "16px 24px",
|
|
80
|
+
"background": "#667eea",
|
|
81
|
+
"display": "flex",
|
|
82
|
+
"justifyContent": "space-between",
|
|
83
|
+
"alignItems": "center"
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<div
|
|
87
|
+
style={{"fontSize": "1.25rem", "fontWeight": "600", "color": "#ffffff"}}
|
|
88
|
+
>
|
|
89
|
+
MyApp
|
|
90
|
+
</div>
|
|
91
|
+
<div
|
|
92
|
+
style={{"display": "flex", "gap": "16px"}}
|
|
93
|
+
>
|
|
94
|
+
<Link
|
|
95
|
+
to="/login"
|
|
96
|
+
style={{"color": "#ffffff", "textDecoration": "none"}}
|
|
97
|
+
>
|
|
98
|
+
Login
|
|
99
|
+
</Link>
|
|
100
|
+
<Link
|
|
101
|
+
to="/signup"
|
|
102
|
+
style={{"color": "#ffffff", "textDecoration": "none"}}
|
|
103
|
+
>
|
|
104
|
+
Sign Up
|
|
105
|
+
</Link>
|
|
106
|
+
</div>
|
|
107
|
+
</nav>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Login Page
|
|
111
|
+
def LoginPage() -> any {
|
|
112
|
+
let [username, setUsername] = useState("");
|
|
113
|
+
let [password, setPassword] = useState("");
|
|
114
|
+
let [error, setError] = useState("");
|
|
115
|
+
let navigate = useNavigate();
|
|
116
|
+
|
|
117
|
+
async def handleLogin(e: any) -> None {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
setError("");
|
|
120
|
+
if not username or not password {
|
|
121
|
+
setError("Please fill in all fields");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
success = await jacLogin(username, password);
|
|
125
|
+
if success {
|
|
126
|
+
navigate("/dashboard");
|
|
127
|
+
} else {
|
|
128
|
+
setError("Invalid credentials");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
def handleUsernameChange(e: any) -> None {
|
|
133
|
+
setUsername(e.target.value);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
def handlePasswordChange(e: any) -> None {
|
|
137
|
+
setPassword(e.target.value);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let errorDisplay = None;
|
|
141
|
+
if error {
|
|
142
|
+
errorDisplay = <div
|
|
143
|
+
style={{"color": "#dc2626", "fontSize": "14px", "marginBottom": "12px"}}
|
|
144
|
+
>
|
|
145
|
+
{error}
|
|
146
|
+
</div>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return <div
|
|
150
|
+
style={{
|
|
151
|
+
"minHeight": "calc(100vh - 56px)",
|
|
152
|
+
"display": "flex",
|
|
153
|
+
"alignItems": "center",
|
|
154
|
+
"justifyContent": "center",
|
|
155
|
+
"background": "#f5f5f5"
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
<div
|
|
159
|
+
style={{
|
|
160
|
+
"background": "#ffffff",
|
|
161
|
+
"padding": "32px",
|
|
162
|
+
"borderRadius": "8px",
|
|
163
|
+
"width": "300px",
|
|
164
|
+
"boxShadow": "0 2px 8px rgba(0,0,0,0.1)"
|
|
165
|
+
}}
|
|
166
|
+
>
|
|
167
|
+
<h2
|
|
168
|
+
style={{"marginBottom": "24px", "textAlign": "center"}}
|
|
169
|
+
>
|
|
170
|
+
Login
|
|
171
|
+
</h2>
|
|
172
|
+
<form
|
|
173
|
+
onSubmit={handleLogin}
|
|
174
|
+
>
|
|
175
|
+
<input
|
|
176
|
+
type="text"
|
|
177
|
+
value={username}
|
|
178
|
+
onChange={handleUsernameChange}
|
|
179
|
+
placeholder="Username"
|
|
180
|
+
style={{
|
|
181
|
+
"width": "100%",
|
|
182
|
+
"padding": "10px",
|
|
183
|
+
"marginBottom": "12px",
|
|
184
|
+
"border": "1px solid #ddd",
|
|
185
|
+
"borderRadius": "4px",
|
|
186
|
+
"boxSizing": "border-box"
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
<input
|
|
190
|
+
type="password"
|
|
191
|
+
value={password}
|
|
192
|
+
onChange={handlePasswordChange}
|
|
193
|
+
placeholder="Password"
|
|
194
|
+
style={{
|
|
195
|
+
"width": "100%",
|
|
196
|
+
"padding": "10px",
|
|
197
|
+
"marginBottom": "12px",
|
|
198
|
+
"border": "1px solid #ddd",
|
|
199
|
+
"borderRadius": "4px",
|
|
200
|
+
"boxSizing": "border-box"
|
|
201
|
+
}}
|
|
202
|
+
/>
|
|
203
|
+
{errorDisplay}
|
|
204
|
+
<button
|
|
205
|
+
type="submit"
|
|
206
|
+
style={{
|
|
207
|
+
"width": "100%",
|
|
208
|
+
"padding": "10px",
|
|
209
|
+
"background": "#667eea",
|
|
210
|
+
"color": "#ffffff",
|
|
211
|
+
"border": "none",
|
|
212
|
+
"borderRadius": "4px",
|
|
213
|
+
"cursor": "pointer",
|
|
214
|
+
"fontWeight": "600"
|
|
215
|
+
}}
|
|
216
|
+
>
|
|
217
|
+
Login
|
|
218
|
+
</button>
|
|
219
|
+
</form>
|
|
220
|
+
<p
|
|
221
|
+
style={{
|
|
222
|
+
"textAlign": "center",
|
|
223
|
+
"marginTop": "16px",
|
|
224
|
+
"fontSize": "14px"
|
|
225
|
+
}}
|
|
226
|
+
>
|
|
227
|
+
Need an account?
|
|
228
|
+
<Link to="/signup">
|
|
229
|
+
Sign up
|
|
230
|
+
</Link>
|
|
231
|
+
</p>
|
|
232
|
+
</div>
|
|
233
|
+
</div>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# Signup Page
|
|
237
|
+
def SignupPage() -> any {
|
|
238
|
+
let [username, setUsername] = useState("");
|
|
239
|
+
let [password, setPassword] = useState("");
|
|
240
|
+
let [error, setError] = useState("");
|
|
241
|
+
let navigate = useNavigate();
|
|
242
|
+
|
|
243
|
+
async def handleSignup(e: any) -> None {
|
|
244
|
+
e.preventDefault();
|
|
245
|
+
setError("");
|
|
246
|
+
if not username or not password {
|
|
247
|
+
setError("Please fill in all fields");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
result = await jacSignup(username, password);
|
|
251
|
+
if result["success"] {
|
|
252
|
+
navigate("/dashboard");
|
|
253
|
+
} else {
|
|
254
|
+
setError(result["error"] if result["error"] else "Signup failed");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
def handleUsernameChange(e: any) -> None {
|
|
259
|
+
setUsername(e.target.value);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
def handlePasswordChange(e: any) -> None {
|
|
263
|
+
setPassword(e.target.value);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
let errorDisplay = None;
|
|
267
|
+
if error {
|
|
268
|
+
errorDisplay = <div
|
|
269
|
+
style={{"color": "#dc2626", "fontSize": "14px", "marginBottom": "12px"}}
|
|
270
|
+
>
|
|
271
|
+
{error}
|
|
272
|
+
</div>;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return <div
|
|
276
|
+
style={{
|
|
277
|
+
"minHeight": "calc(100vh - 56px)",
|
|
278
|
+
"display": "flex",
|
|
279
|
+
"alignItems": "center",
|
|
280
|
+
"justifyContent": "center",
|
|
281
|
+
"background": "#f5f5f5"
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
<div
|
|
285
|
+
style={{
|
|
286
|
+
"background": "#ffffff",
|
|
287
|
+
"padding": "32px",
|
|
288
|
+
"borderRadius": "8px",
|
|
289
|
+
"width": "300px",
|
|
290
|
+
"boxShadow": "0 2px 8px rgba(0,0,0,0.1)"
|
|
291
|
+
}}
|
|
292
|
+
>
|
|
293
|
+
<h2
|
|
294
|
+
style={{"marginBottom": "24px", "textAlign": "center"}}
|
|
295
|
+
>
|
|
296
|
+
Sign Up
|
|
297
|
+
</h2>
|
|
298
|
+
<form
|
|
299
|
+
onSubmit={handleSignup}
|
|
300
|
+
>
|
|
301
|
+
<input
|
|
302
|
+
type="text"
|
|
303
|
+
value={username}
|
|
304
|
+
onChange={handleUsernameChange}
|
|
305
|
+
placeholder="Username"
|
|
306
|
+
style={{
|
|
307
|
+
"width": "100%",
|
|
308
|
+
"padding": "10px",
|
|
309
|
+
"marginBottom": "12px",
|
|
310
|
+
"border": "1px solid #ddd",
|
|
311
|
+
"borderRadius": "4px",
|
|
312
|
+
"boxSizing": "border-box"
|
|
313
|
+
}}
|
|
314
|
+
/>
|
|
315
|
+
<input
|
|
316
|
+
type="password"
|
|
317
|
+
value={password}
|
|
318
|
+
onChange={handlePasswordChange}
|
|
319
|
+
placeholder="Password"
|
|
320
|
+
style={{
|
|
321
|
+
"width": "100%",
|
|
322
|
+
"padding": "10px",
|
|
323
|
+
"marginBottom": "12px",
|
|
324
|
+
"border": "1px solid #ddd",
|
|
325
|
+
"borderRadius": "4px",
|
|
326
|
+
"boxSizing": "border-box"
|
|
327
|
+
}}
|
|
328
|
+
/>
|
|
329
|
+
{errorDisplay}
|
|
330
|
+
<button
|
|
331
|
+
type="submit"
|
|
332
|
+
style={{
|
|
333
|
+
"width": "100%",
|
|
334
|
+
"padding": "10px",
|
|
335
|
+
"background": "#667eea",
|
|
336
|
+
"color": "#ffffff",
|
|
337
|
+
"border": "none",
|
|
338
|
+
"borderRadius": "4px",
|
|
339
|
+
"cursor": "pointer",
|
|
340
|
+
"fontWeight": "600"
|
|
341
|
+
}}
|
|
342
|
+
>
|
|
343
|
+
Sign Up
|
|
344
|
+
</button>
|
|
345
|
+
</form>
|
|
346
|
+
<p
|
|
347
|
+
style={{
|
|
348
|
+
"textAlign": "center",
|
|
349
|
+
"marginTop": "16px",
|
|
350
|
+
"fontSize": "14px"
|
|
351
|
+
}}
|
|
352
|
+
>
|
|
353
|
+
Have an account?
|
|
354
|
+
<Link to="/login">
|
|
355
|
+
Login
|
|
356
|
+
</Link>
|
|
357
|
+
</p>
|
|
358
|
+
</div>
|
|
359
|
+
</div>;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
# Dashboard Page (Protected Route)
|
|
363
|
+
def DashboardPage() -> any {
|
|
364
|
+
# Check if user is logged in, redirect if not
|
|
365
|
+
if not jacIsLoggedIn() {
|
|
366
|
+
return <Navigate to="/login" />;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return <div
|
|
370
|
+
style={{
|
|
371
|
+
"minHeight": "calc(100vh - 56px)",
|
|
372
|
+
"padding": "40px 20px",
|
|
373
|
+
"background": "#f5f5f5"
|
|
374
|
+
}}
|
|
375
|
+
>
|
|
376
|
+
<div
|
|
377
|
+
style={{
|
|
378
|
+
"maxWidth": "800px",
|
|
379
|
+
"margin": "0 auto",
|
|
380
|
+
"background": "#ffffff",
|
|
381
|
+
"padding": "40px",
|
|
382
|
+
"borderRadius": "8px",
|
|
383
|
+
"boxShadow": "0 2px 8px rgba(0,0,0,0.1)"
|
|
384
|
+
}}
|
|
385
|
+
>
|
|
386
|
+
<h1
|
|
387
|
+
style={{"marginBottom": "16px"}}
|
|
388
|
+
>
|
|
389
|
+
🎉 Welcome to Your Dashboard
|
|
390
|
+
</h1>
|
|
391
|
+
<p
|
|
392
|
+
style={{"color": "#666", "lineHeight": "1.6"}}
|
|
393
|
+
>
|
|
394
|
+
You are now logged in and can access protected content.
|
|
395
|
+
</p>
|
|
396
|
+
<p
|
|
397
|
+
style={{"color": "#666", "lineHeight": "1.6", "marginTop": "16px"}}
|
|
398
|
+
>
|
|
399
|
+
This is a simple dashboard page demonstrating authenticationwith React Router in Jac. You can add your own content and functionality here.
|
|
400
|
+
</p>
|
|
401
|
+
<div
|
|
402
|
+
style={{
|
|
403
|
+
"marginTop": "24px",
|
|
404
|
+
"padding": "16px",
|
|
405
|
+
"background": "#f0f9ff",
|
|
406
|
+
"borderRadius": "4px",
|
|
407
|
+
"border": "1px solid #bae6fd"
|
|
408
|
+
}}
|
|
409
|
+
>
|
|
410
|
+
<h3
|
|
411
|
+
style={{"marginBottom": "8px", "color": "#0369a1"}}
|
|
412
|
+
>
|
|
413
|
+
Protected Route Demo
|
|
414
|
+
</h3>
|
|
415
|
+
<p
|
|
416
|
+
style={{"color": "#0c4a6e", "fontSize": "14px"}}
|
|
417
|
+
>
|
|
418
|
+
This page is only accessible to authenticated users. Try logging outand accessing this page - you'll be redirected to the login page!
|
|
419
|
+
</p>
|
|
420
|
+
</div>
|
|
421
|
+
</div>
|
|
422
|
+
</div>;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
# Home/Landing Page - auto-redirect based on auth status
|
|
426
|
+
def HomePage() -> any {
|
|
427
|
+
if jacIsLoggedIn() {
|
|
428
|
+
return <Navigate to="/dashboard" />;
|
|
429
|
+
}
|
|
430
|
+
return <Navigate to="/login" />;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
# Main App with React Router
|
|
434
|
+
def app() -> any {
|
|
435
|
+
return <Router>
|
|
436
|
+
<div
|
|
437
|
+
style={{
|
|
438
|
+
"fontFamily": "system-ui, -apple-system, sans-serif",
|
|
439
|
+
"minHeight": "100vh"
|
|
440
|
+
}}
|
|
441
|
+
>
|
|
442
|
+
<Navigation />
|
|
443
|
+
<Routes>
|
|
444
|
+
<Route
|
|
445
|
+
path="/"
|
|
446
|
+
element={<HomePage />}
|
|
447
|
+
/>
|
|
448
|
+
<Route
|
|
449
|
+
path="/login"
|
|
450
|
+
element={<LoginPage />}
|
|
451
|
+
/>
|
|
452
|
+
<Route
|
|
453
|
+
path="/signup"
|
|
454
|
+
element={<SignupPage />}
|
|
455
|
+
/>
|
|
456
|
+
<Route
|
|
457
|
+
path="/dashboard"
|
|
458
|
+
element={<DashboardPage />}
|
|
459
|
+
/>
|
|
460
|
+
</Routes>
|
|
461
|
+
</div>
|
|
462
|
+
</Router>;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "basic-auth-with-router",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "npm run compile && vite build",
|
|
7
|
+
"dev": "vite dev",
|
|
8
|
+
"preview": "vite preview",
|
|
9
|
+
"compile": "babel src --out-dir build --extensions \".jsx,.js\" --out-file-extension .js"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"description": "Jac application: basic-auth-with-router",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"vite": "^6.4.1",
|
|
18
|
+
"@babel/cli": "^7.28.3",
|
|
19
|
+
"@babel/core": "^7.28.5",
|
|
20
|
+
"@babel/preset-env": "^7.28.5",
|
|
21
|
+
"@babel/preset-react": "^7.28.5"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"react": "^19.2.0",
|
|
25
|
+
"react-dom": "^19.2.0",
|
|
26
|
+
"react-router-dom": "^6.30.1"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
root: ".", // base folder
|
|
10
|
+
build: {
|
|
11
|
+
rollupOptions: {
|
|
12
|
+
input: "build/main.js", // your compiled entry file
|
|
13
|
+
output: {
|
|
14
|
+
entryFileNames: "client.[hash].js", // name of the final js file
|
|
15
|
+
assetFileNames: "[name].[ext]",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
outDir: "dist", // final bundled output
|
|
19
|
+
emptyOutDir: true,
|
|
20
|
+
},
|
|
21
|
+
publicDir: false,
|
|
22
|
+
resolve: {
|
|
23
|
+
alias: {
|
|
24
|
+
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|