miolo 3.0.0-beta.21 → 3.0.0-beta.210

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 (246) hide show
  1. package/bin/build/build.mjs +53 -0
  2. package/bin/build/build_bin.mjs +17 -0
  3. package/bin/build/cli/client.mjs +52 -0
  4. package/bin/build/cli/css.mjs +22 -0
  5. package/bin/build/cli/index.mjs +40 -0
  6. package/bin/build/cli/ssr.mjs +21 -0
  7. package/bin/build/server/aliases.mjs +112 -0
  8. package/bin/build/server/babel.config.js +24 -0
  9. package/bin/build/server/banner.mjs +20 -0
  10. package/bin/build/server/bundle.mjs +111 -0
  11. package/bin/build/server/fix.mjs +15 -0
  12. package/bin/build/server/index.mjs +69 -0
  13. package/bin/build/server/options.mjs +83 -0
  14. package/bin/create/auth.mjs +23 -0
  15. package/bin/create/copy.mjs +175 -0
  16. package/bin/create/docker.mjs +25 -0
  17. package/bin/create/index.mjs +137 -0
  18. package/bin/create/pkgjson.mjs +72 -0
  19. package/bin/create/prepare-template.mjs +158 -0
  20. package/bin/create/validation.mjs +27 -0
  21. package/bin/dev/dev.mjs +32 -23
  22. package/bin/dev/dev_start.mjs +6 -5
  23. package/bin/index.mjs +94 -52
  24. package/bin/prod-bin/create-bin.mjs +42 -27
  25. package/bin/prod-bin/run.mjs +13 -9
  26. package/bin/{prod-run → run}/pid.mjs +4 -4
  27. package/bin/run/restart.mjs +13 -0
  28. package/bin/run/start.mjs +18 -0
  29. package/bin/run/stop.mjs +20 -0
  30. package/bin/util.mjs +35 -11
  31. package/package.json +59 -39
  32. package/src/config/.env +34 -12
  33. package/src/config/defaults.mjs +253 -185
  34. package/src/config/env.mjs +40 -22
  35. package/src/config/index.mjs +19 -24
  36. package/src/config/util.mjs +25 -10
  37. package/src/db-conn.mjs +34 -0
  38. package/src/engines/cron/emails.mjs +10 -5
  39. package/src/engines/cron/index.mjs +45 -51
  40. package/src/engines/cron/init.mjs +16 -17
  41. package/src/engines/cron/ipsum.mjs +65 -60
  42. package/src/engines/cron/syscheck.mjs +30 -30
  43. package/src/engines/emailer/index.mjs +1 -2
  44. package/src/engines/emailer/queue.mjs +14 -20
  45. package/src/engines/emailer/transporter.mjs +86 -74
  46. package/src/engines/geoip/index.mjs +23 -28
  47. package/src/engines/http/index.mjs +26 -15
  48. package/src/engines/logger/buildErrorEmailBody.mjs +72 -0
  49. package/src/engines/logger/index.mjs +114 -122
  50. package/src/engines/logger/injectStackTrace.mjs +59 -0
  51. package/src/engines/logger/logger_mail.mjs +47 -61
  52. package/src/engines/logger/reopenTransportOnHupSignal.mjs +12 -13
  53. package/src/engines/parser/Parser.mjs +77 -60
  54. package/src/engines/parser/index.mjs +1 -1
  55. package/src/engines/schema/diffObjs.mjs +41 -0
  56. package/src/engines/schema/index.mjs +4 -0
  57. package/src/engines/schema/input.mjs +54 -0
  58. package/src/engines/schema/output.mjs +66 -0
  59. package/src/engines/socket/index.mjs +44 -46
  60. package/src/index.mjs +15 -10
  61. package/src/middleware/auth/basic.mjs +41 -40
  62. package/src/middleware/auth/custom.mjs +10 -13
  63. package/src/middleware/auth/guest.mjs +27 -27
  64. package/src/middleware/auth/passport/index.mjs +374 -0
  65. package/src/middleware/auth/passport/session/index.mjs +43 -0
  66. package/src/middleware/auth/{credentials → passport}/session/store.mjs +35 -15
  67. package/src/middleware/auth/passport/session/store_koa_redis.mjs +3 -0
  68. package/src/middleware/context/cache/index.mjs +78 -33
  69. package/src/middleware/context/cache/options.mjs +19 -21
  70. package/src/middleware/context/db.mjs +45 -20
  71. package/src/middleware/context/index.mjs +12 -12
  72. package/src/middleware/extra.mjs +4 -5
  73. package/src/middleware/http/body.mjs +25 -25
  74. package/src/middleware/http/catcher.mjs +81 -8
  75. package/src/middleware/http/custom_blacklist.mjs +19 -16
  76. package/src/middleware/http/headers.mjs +37 -34
  77. package/src/middleware/http/ratelimit.mjs +16 -23
  78. package/src/middleware/http/request.mjs +60 -65
  79. package/src/middleware/routes/catch_js_error.mjs +30 -23
  80. package/src/middleware/routes/robots.mjs +4 -7
  81. package/src/middleware/routes/router/crud/attachCrudRoutes.mjs +108 -90
  82. package/src/middleware/routes/router/crud/getCrudConfig.mjs +31 -55
  83. package/src/middleware/routes/router/defaults.mjs +6 -19
  84. package/src/middleware/routes/router/index.mjs +17 -21
  85. package/src/middleware/routes/router/queries/attachQueriesRoutes.mjs +227 -50
  86. package/src/middleware/routes/router/queries/getQueriesConfig.mjs +45 -55
  87. package/src/middleware/routes/router/utils.mjs +41 -26
  88. package/src/middleware/ssr/context.mjs +5 -7
  89. package/src/middleware/ssr/html.mjs +66 -43
  90. package/src/middleware/ssr/loader.mjs +11 -14
  91. package/src/middleware/ssr/ssr_render.mjs +39 -22
  92. package/src/middleware/static/index.mjs +33 -14
  93. package/src/middleware/vite/devserver.mjs +38 -22
  94. package/src/middleware/vite/watcher.mjs +12 -14
  95. package/src/server-cron.mjs +13 -8
  96. package/src/server-dev.mjs +13 -16
  97. package/src/server.mjs +49 -51
  98. package/template/.agent/skills/miolo-app-arch/SKILL.md +218 -0
  99. package/template/.agent/skills/miolo-auth/SKILL.md +450 -0
  100. package/template/.agent/skills/miolo-cli-router/SKILL.md +394 -0
  101. package/template/.agent/skills/miolo-database/SKILL.md +358 -0
  102. package/template/.agent/skills/miolo-react-patterns/SKILL.md +426 -0
  103. package/template/.agent/skills/miolo-routing/SKILL.md +326 -0
  104. package/template/.agent/skills/miolo-schemas/SKILL.md +329 -0
  105. package/template/.agent/skills/miolo-session-context/SKILL.md +397 -0
  106. package/template/.agent/skills/miolo-ssr/SKILL.md +433 -0
  107. package/template/.editorconfig +18 -0
  108. package/template/.env +120 -0
  109. package/template/biome.json +63 -0
  110. package/template/components.json +21 -0
  111. package/template/db/init.sh +89 -0
  112. package/template/db/sql/00_drop.sql +2 -0
  113. package/template/db/sql/01_users.sql +31 -0
  114. package/template/db/sql/02_todos.sql +20 -0
  115. package/template/docker/Dockerfile +13 -0
  116. package/template/docker/docker-compose.yaml +79 -0
  117. package/template/gitignore +42 -0
  118. package/template/jsconfig.json +18 -0
  119. package/template/package.json +88 -0
  120. package/template/postcss.config.js +9 -0
  121. package/template/src/cli/App.jsx +25 -0
  122. package/template/src/cli/components/JsonTreeViewer.jsx +128 -0
  123. package/template/src/cli/components/shadcn-io/spinner/index.jsx +232 -0
  124. package/template/src/cli/components/stepper.jsx +408 -0
  125. package/template/src/cli/components/ui/avatar.jsx +36 -0
  126. package/template/src/cli/components/ui/badge.jsx +31 -0
  127. package/template/src/cli/components/ui/breadcrumb.jsx +97 -0
  128. package/template/src/cli/components/ui/card.jsx +73 -0
  129. package/template/src/cli/components/ui/collapsible.jsx +16 -0
  130. package/template/src/cli/components/ui/dropdown-menu.jsx +179 -0
  131. package/template/src/cli/components/ui/field.jsx +217 -0
  132. package/template/src/cli/components/ui/input.jsx +19 -0
  133. package/template/src/cli/components/ui/label.jsx +17 -0
  134. package/template/src/cli/components/ui/pagination.jsx +99 -0
  135. package/template/src/cli/components/ui/patched/alert.jsx +56 -0
  136. package/template/src/cli/components/ui/patched/button.jsx +45 -0
  137. package/template/src/cli/components/ui/patched/dialog.jsx +114 -0
  138. package/template/src/cli/components/ui/patched/sidebar.jsx +660 -0
  139. package/template/src/cli/components/ui/select.jsx +141 -0
  140. package/template/src/cli/components/ui/separator.jsx +21 -0
  141. package/template/src/cli/components/ui/sheet.jsx +115 -0
  142. package/template/src/cli/components/ui/skeleton.jsx +13 -0
  143. package/template/src/cli/components/ui/sonner.jsx +22 -0
  144. package/template/src/cli/components/ui/switch.jsx +25 -0
  145. package/template/src/cli/components/ui/table.jsx +88 -0
  146. package/template/src/cli/components/ui/textarea.jsx +16 -0
  147. package/template/src/cli/components/ui/tooltip.jsx +45 -0
  148. package/template/src/cli/config/store_keys.mjs +2 -0
  149. package/template/src/cli/context/data/DataContext.jsx +5 -0
  150. package/template/src/cli/context/data/DataProvider.jsx +44 -0
  151. package/template/src/cli/context/data/useBreads.mjs +15 -0
  152. package/template/src/cli/context/data/useDataContext.mjs +4 -0
  153. package/template/src/cli/context/session/SessionContext.mjs +4 -0
  154. package/template/src/cli/context/session/SessionProvider.jsx +31 -0
  155. package/template/src/cli/context/session/makePermissioner.mjs +34 -0
  156. package/template/src/cli/context/session/useSessionContext.mjs +6 -0
  157. package/template/src/cli/context/theme/ThemeContext.mjs +4 -0
  158. package/template/src/cli/context/theme/ThemeProvider.jsx +49 -0
  159. package/template/src/cli/context/theme/useThemeContext.mjs +6 -0
  160. package/template/src/cli/context/ui/UIContext.jsx +5 -0
  161. package/template/src/cli/context/ui/UIProvider.jsx +16 -0
  162. package/template/src/cli/context/ui/useUIContext.mjs +4 -0
  163. package/template/src/cli/context/util.mjs +17 -0
  164. package/template/src/cli/entry-cli.jsx +33 -0
  165. package/template/src/cli/hooks/useIsMobile.mjs +19 -0
  166. package/template/src/cli/hooks/useStoragedState.mjs +63 -0
  167. package/template/src/cli/index.html +29 -0
  168. package/template/src/cli/layout/app-sidebar.jsx +25 -0
  169. package/template/src/cli/layout/main-layout.jsx +63 -0
  170. package/template/src/cli/layout/nav-last-todos.jsx +72 -0
  171. package/template/src/cli/layout/nav-main.jsx +39 -0
  172. package/template/src/cli/layout/nav-user.jsx +105 -0
  173. package/template/src/cli/layout/prop-switcher.jsx +93 -0
  174. package/template/src/cli/lib/utils.mjs +10 -0
  175. package/template/src/cli/pages/Index.jsx +13 -0
  176. package/template/src/cli/pages/IndexOffline.jsx +13 -0
  177. package/template/src/cli/pages/IndexOnline.jsx +18 -0
  178. package/template/src/cli/pages/dash/Dashboard.jsx +29 -0
  179. package/template/src/cli/pages/offline/Login.jsx +43 -0
  180. package/template/src/cli/pages/offline/LoginForm.jsx +115 -0
  181. package/template/src/cli/pages/security/Security.jsx +39 -0
  182. package/template/src/cli/pages/security/SecurityForm.jsx +106 -0
  183. package/template/src/cli/pages/todos/TodoActions.jsx +99 -0
  184. package/template/src/cli/pages/todos/TodoAdd.jsx +43 -0
  185. package/template/src/cli/pages/todos/TodoList.jsx +60 -0
  186. package/template/src/cli/pages/todos/Todos.jsx +23 -0
  187. package/template/src/cli/pages/todos/context/TodosContext.jsx +5 -0
  188. package/template/src/cli/pages/todos/context/TodosProvider.jsx +191 -0
  189. package/template/src/cli/pages/todos/context/useTodosContext.mjs +4 -0
  190. package/template/src/ns/models/Todo.mjs +29 -0
  191. package/template/src/ns/models/TodoList.mjs +8 -0
  192. package/template/src/ns/models/User.mjs +40 -0
  193. package/template/src/server/bot/check_today.mjs +10 -0
  194. package/template/src/server/io/cache/base.mjs +21 -0
  195. package/template/src/server/io/db/filter.mjs +92 -0
  196. package/template/src/server/io/db/todos/delete.mjs +29 -0
  197. package/template/src/server/io/db/todos/find.mjs +13 -0
  198. package/template/src/server/io/db/todos/read.mjs +83 -0
  199. package/template/src/server/io/db/todos/toggle.mjs +37 -0
  200. package/template/src/server/io/db/todos/upsave.mjs +32 -0
  201. package/template/src/server/io/db/triggers/user.mjs +13 -0
  202. package/template/src/server/io/db/users/auth.mjs +132 -0
  203. package/template/src/server/io/db/users/pwd.mjs +38 -0
  204. package/template/src/server/io/db/users/save.mjs +17 -0
  205. package/template/src/server/miolo/auth/basic.mjs +15 -0
  206. package/template/src/server/miolo/auth/guest.mjs +3 -0
  207. package/template/src/server/miolo/auth/passport.mjs +73 -0
  208. package/template/src/server/miolo/cache.mjs +11 -0
  209. package/template/src/server/miolo/cron/foo.mjs +7 -0
  210. package/template/src/server/miolo/cron/index.mjs +28 -0
  211. package/template/src/server/miolo/cron/invalidate.mjs +21 -0
  212. package/template/src/server/miolo/db.mjs +36 -0
  213. package/template/src/server/miolo/http.mjs +14 -0
  214. package/template/src/server/miolo/index.mjs +43 -0
  215. package/template/src/server/miolo/routes/crud.mjs +16 -0
  216. package/template/src/server/miolo/routes/index.mjs +8 -0
  217. package/template/src/server/miolo/ssr/entry-server.jsx +13 -0
  218. package/template/src/server/miolo/ssr/loader.mjs +18 -0
  219. package/template/src/server/routes/index.mjs +66 -0
  220. package/template/src/server/routes/todos/mod.mjs +52 -0
  221. package/template/src/server/routes/todos/read.mjs +45 -0
  222. package/template/src/server/routes/todos/special.mjs +47 -0
  223. package/template/src/server/routes/users/user.mjs +54 -0
  224. package/template/src/server/server.mjs +10 -0
  225. package/template/src/server/utils/crypt.mjs +38 -0
  226. package/template/src/server/utils/io.mjs +15 -0
  227. package/template/src/server/utils/pwdfor.mjs +25 -0
  228. package/template/src/server/utils/schema.mjs +22 -0
  229. package/template/src/static/img/default/profile.png +0 -0
  230. package/template/src/static/img/favicon.ico +0 -0
  231. package/template/src/static/img/miolo_logo.png +0 -0
  232. package/template/src/static/img/miolo_name.png +0 -0
  233. package/template/src/static/public/manifest.json +21 -0
  234. package/template/src/static/public/sw.js +79 -0
  235. package/template/src/static/style/globals.css +156 -0
  236. package/template/src/static/style/json-tree.css +54 -0
  237. package/template/src/static/style/skeleton.css +49 -0
  238. package/bin/prod-build/build-client.mjs +0 -67
  239. package/bin/prod-build/build-server.mjs +0 -58
  240. package/bin/prod-run/restart.mjs +0 -9
  241. package/bin/prod-run/start.mjs +0 -15
  242. package/bin/prod-run/stop.mjs +0 -20
  243. package/src/engines/logger/verify.mjs +0 -22
  244. package/src/middleware/auth/credentials/index.mjs +0 -151
  245. package/src/middleware/auth/credentials/session/index.mjs +0 -24
  246. package/src/middleware/auth/credentials/session/store_koa_redis.mjs +0 -3
@@ -0,0 +1,397 @@
1
+ ---
2
+ name: miolo-session-context
3
+ description: Session and context management for miolo applications. Use when working with user authentication, session state, context properties in routes/middleware (backend), or useMioloContext/SessionProvider (client). For permissions, fetcher, and SSR, see separate skills.
4
+ ---
5
+
6
+ # Miolo Session & Context Management
7
+
8
+ Session and authentication context management in miolo applications (backend and client).
9
+
10
+ ## Backend (Server-Side Context)
11
+
12
+ In route handlers and middleware, the `ctx` object provides access to request data and session state.
13
+
14
+ ### Request Properties
15
+
16
+ Access request data through `ctx.request`:
17
+
18
+ ```javascript
19
+ export async function r_create_item(ctx, params) {
20
+ // Request body (POST data)
21
+ const body = ctx.request.body
22
+
23
+ // Client IP address
24
+ const clientIp = ctx.request.ip
25
+
26
+ ctx.miolo.logger.info(`Request from IP: ${clientIp}`)
27
+
28
+ return { ok: true, data: body }
29
+ }
30
+ ```
31
+
32
+ **Available properties:**
33
+ - `ctx.request.body` - POST/PUT request body
34
+ - `ctx.request.ip` - Client IP address
35
+
36
+ ### Session Properties (All Auth Methods)
37
+
38
+ Common session properties available regardless of auth strategy:
39
+
40
+ ```javascript
41
+ export async function r_get_profile(ctx, params) {
42
+ // User object (null if not authenticated)
43
+ const user = ctx.session.user
44
+
45
+ // Authentication status (boolean)
46
+ const isAuth = ctx.session.authenticated
47
+
48
+ // Token (if using guest auth)
49
+ const token = ctx.session.token
50
+
51
+ if (!ctx.session.authenticated) {
52
+ return { ok: false, error: 'Not authenticated' }
53
+ }
54
+
55
+ return { ok: true, data: ctx.session.user }
56
+ }
57
+ ```
58
+
59
+ **Available properties:**
60
+ - `ctx.session.user` - User object (or `null`)
61
+ - `ctx.session.authenticated` - Boolean authentication status
62
+ - `ctx.session.auth_method` - Authentication method (local, google, etc.)
63
+ - `ctx.session.token` - Auth token (guest auth only)
64
+
65
+ ### Credentials Auth Methods
66
+
67
+ When using local authentication strategy, additional methods are available:
68
+
69
+ ```javascript
70
+ export async function r_user_login(ctx, params) {
71
+ const { username, password } = params
72
+
73
+ // Attempt login
74
+ await ctx.login(username, password)
75
+
76
+ // Check authentication status
77
+ if (ctx.isAuthenticated()) {
78
+ ctx.miolo.logger.info(`User ${ctx.state.user.id} logged in`)
79
+ return { ok: true, user: ctx.state.user }
80
+ }
81
+
82
+ return { ok: false, error: 'Invalid credentials' }
83
+ }
84
+
85
+ export async function r_user_logout(ctx, params) {
86
+ ctx.logout()
87
+ return { ok: true }
88
+ }
89
+
90
+ export async function r_protected_route(ctx, params) {
91
+ // Check if NOT authenticated
92
+ if (ctx.isUnauthenticated()) {
93
+ return { ok: false, error: 'Authentication required' }
94
+ }
95
+
96
+ // Access authenticated user
97
+ const user = ctx.state.user
98
+
99
+ return { ok: true, data: user }
100
+ }
101
+ ```
102
+
103
+ **Available methods (local auth):**
104
+ - `ctx.isAuthenticated()` - Returns `true` if user is authenticated
105
+ - `ctx.isUnauthenticated()` - Returns `true` if user is NOT authenticated
106
+ - `await ctx.login(username, password)` - Attempt to authenticate user
107
+ - `ctx.logout()` - End user session
108
+
109
+ **User access:**
110
+ - `ctx.state.user` - Authenticated user object (local auth)
111
+ - `ctx.session.user` - User object (all auth methods)
112
+
113
+ ### Backend Usage Example
114
+
115
+ Complete route handler using session:
116
+
117
+ ```javascript
118
+ export async function r_user_operation(ctx, params) {
119
+ try {
120
+ // Check authentication
121
+ if (!ctx.session.authenticated) {
122
+ return { ok: false, error: 'Authentication required' }
123
+ }
124
+
125
+ // Access user data
126
+ const userId = ctx.session.user.id
127
+ const userEmail = ctx.session.user.email
128
+
129
+ // Log with user context
130
+ ctx.miolo.logger.info(`[r_user_operation] User ${userId} performing operation`)
131
+
132
+ // Perform operation
133
+ const result = await db_user_operation(ctx, {
134
+ ...params,
135
+ user_id: userId
136
+ })
137
+
138
+ return { ok: true, data: result }
139
+
140
+ } catch (error) {
141
+ ctx.miolo.logger.error(`[r_user_operation] Error: ${error}`)
142
+ return { ok: false, error: error?.message }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ## Client-Side (React Context)
148
+
149
+ ### useMioloContext Hook
150
+
151
+ The `useMioloContext` hook from `miolo-react` provides core session functionality:
152
+
153
+ ```javascript
154
+ import { useMioloContext } from 'miolo-react'
155
+
156
+ function MyComponent() {
157
+ const {
158
+ user,
159
+ updateUser,
160
+ authenticated,
161
+ fetcher,
162
+ login,
163
+ logout,
164
+ useSsrData
165
+ } = useMioloContext()
166
+
167
+ if (!authenticated) {
168
+ return <div>Please log in</div>
169
+ }
170
+
171
+ return (
172
+ <div>
173
+ <h1>Welcome {user.name}</h1>
174
+ <button onClick={logout}>Logout</button>
175
+ </div>
176
+ )
177
+ }
178
+ ```
179
+
180
+ **Available properties:**
181
+ - `user` - User object (or `null` if not authenticated)
182
+ - `updateUser(userData)` - Update user data in context
183
+ - `authenticated` - Boolean authentication status
184
+ - `fetcher` - Fetch wrapper with auth (see miolo-fetcher skill)
185
+ - `login(credentials)` - Authenticate user
186
+ - `logout()` - End session
187
+ - `useSsrData()` - Access SSR data (see miolo-ssr skill)
188
+
189
+ ### SessionProvider Wrapper
190
+
191
+ The application typically wraps `useMioloContext` in a `SessionProvider` for additional functionality:
192
+
193
+ **File:** `src/cli/context/session/SessionProvider.jsx`
194
+
195
+ ```javascript
196
+ import { useState, useEffect } from 'react'
197
+ import { useMioloContext } from 'miolo-react'
198
+ import SessionContext from './SessionContext.mjs'
199
+ import makePermissioner from './makePermissioner.mjs'
200
+
201
+ const SessionProvider = ({ children }) => {
202
+ const { user, ...props } = useMioloContext()
203
+ const [permiss, setPermiss] = useState(makePermissioner(user))
204
+
205
+ useEffect(() => {
206
+ setPermiss(makePermissioner(user))
207
+ }, [user])
208
+
209
+ return (
210
+ <SessionContext.Provider value={{
211
+ session: user,
212
+ permiss,
213
+ ...props
214
+ }}>
215
+ {children}
216
+ </SessionContext.Provider>
217
+ )
218
+ }
219
+
220
+ export default SessionProvider
221
+ ```
222
+
223
+ **Adds:**
224
+ - `session` - Alias for user object
225
+ - `permiss` - Permissions object (see miolo-permissions skill)
226
+ - Passes through all `useMioloContext` properties
227
+
228
+ ### useSessionContext Hook
229
+
230
+ Access the wrapped session context:
231
+
232
+ **File:** `src/cli/context/session/useSessionContext.mjs`
233
+
234
+ ```javascript
235
+ import { useContext } from 'react'
236
+ import SessionContext from './SessionContext.mjs'
237
+
238
+ export default function useSessionContext() {
239
+ const context = useContext(SessionContext)
240
+
241
+ if (!context) {
242
+ throw new Error('useSessionContext must be used within SessionProvider')
243
+ }
244
+
245
+ return context
246
+ }
247
+ ```
248
+
249
+ **Usage:**
250
+ ```javascript
251
+ import useSessionContext from '#cli/context/session/useSessionContext.mjs'
252
+
253
+ function ProfilePage() {
254
+ const {
255
+ session, // User object
256
+ permiss, // Permissions
257
+ authenticated,
258
+ logout
259
+ } = useSessionContext()
260
+
261
+ if (!authenticated) {
262
+ return <LoginPage />
263
+ }
264
+
265
+ return (
266
+ <div>
267
+ <h1>{session.name}</h1>
268
+ <p>{session.email}</p>
269
+ {permiss.can('admin') && <AdminPanel />}
270
+ <button onClick={logout}>Logout</button>
271
+ </div>
272
+ )
273
+ }
274
+ ```
275
+
276
+ ## Client-Side Usage Examples
277
+
278
+ ### Login Flow
279
+
280
+ ```javascript
281
+ import { useMioloContext } from 'miolo-react'
282
+
283
+ function LoginPage() {
284
+ const { login } = useMioloContext()
285
+ const [username, setUsername] = useState('')
286
+ const [password, setPassword] = useState('')
287
+
288
+ const handleSubmit = async (e) => {
289
+ e.preventDefault()
290
+
291
+ const result = await login({ username, password })
292
+
293
+ if (result.ok) {
294
+ // Login successful, user context updated automatically
295
+ navigate('/dashboard')
296
+ } else {
297
+ alert(result.error)
298
+ }
299
+ }
300
+
301
+ return (
302
+ <form onSubmit={handleSubmit}>
303
+ <input
304
+ value={username}
305
+ onChange={(e) => setUsername(e.target.value)}
306
+ />
307
+ <input
308
+ type="password"
309
+ value={password}
310
+ onChange={(e) => setPassword(e.target.value)}
311
+ />
312
+ <button type="submit">Login</button>
313
+ </form>
314
+ )
315
+ }
316
+ ```
317
+
318
+ ### Protected Component
319
+
320
+ ```javascript
321
+ import useSessionContext from '#cli/context/session/useSessionContext.mjs'
322
+
323
+ function ProtectedComponent() {
324
+ const { authenticated, session } = useSessionContext()
325
+
326
+ if (!authenticated) {
327
+ return null // Or redirect to login
328
+ }
329
+
330
+ return (
331
+ <div>
332
+ <h2>Protected Content</h2>
333
+ <p>User ID: {session.id}</p>
334
+ </div>
335
+ )
336
+ }
337
+ ```
338
+
339
+ ### Update User Data
340
+
341
+ ```javascript
342
+ import { useMioloContext } from 'miolo-react'
343
+
344
+ function ProfileEditor() {
345
+ const { user, updateUser } = useMioloContext()
346
+
347
+ const handleUpdate = async (newData) => {
348
+ const response = await fetch('/api/user/update', {
349
+ method: 'POST',
350
+ body: JSON.stringify(newData)
351
+ })
352
+
353
+ const result = await response.json()
354
+
355
+ if (result.ok) {
356
+ // Update user in context
357
+ updateUser(result.data)
358
+ }
359
+ }
360
+
361
+ return <ProfileForm onSubmit={handleUpdate} />
362
+ }
363
+ ```
364
+
365
+ ## Best Practices
366
+
367
+ ### Backend
368
+
369
+ 1. **Always check authentication** - Use `ctx.session.authenticated` or `ctx.isAuthenticated()`
370
+ 2. **Use auth in routes** - Configure `auth` in route definition (see miolo-routing skill)
371
+ 3. **Log with user context** - Include user ID in logs for debugging
372
+ 4. **Include user_id in queries** - Enforce data ownership in database queries
373
+ 5. **Handle unauthenticated gracefully** - Return appropriate error messages
374
+
375
+ ### Client
376
+
377
+ 1. **Use SessionProvider** - Wrap useMioloContext for extended functionality
378
+ 2. **Check authenticated state** - Always verify before rendering protected content
379
+ 3. **Handle login errors** - Display meaningful error messages to users
380
+ 4. **Update context on changes** - Use `updateUser()` after profile updates
381
+ 5. **Centralize auth logic** - Use contexts, don't duplicate auth checks
382
+
383
+ ## Related Skills
384
+
385
+ - **miolo-auth** - Authentication strategies and configuration
386
+ - **miolo-routing** - Route protection and auth configuration
387
+ - **miolo-permissions** - Permission system using `permiss` object
388
+ - **miolo-fetcher** - Authenticated API requests (future skill)
389
+ - **miolo-ssr** - Server-side rendering with session (future skill)
390
+
391
+ ## Examples from miolo-sample
392
+
393
+ See actual implementations:
394
+ - `src/server/routes/users/user.mjs` - Backend session usage
395
+ - `src/cli/context/session/SessionProvider.jsx` - SessionProvider wrapper
396
+ - `src/cli/context/session/useSessionContext.mjs` - Session hook
397
+ - `src/cli/pages/Index.jsx` - Auth-based routing