hazo_auth 1.3.0 → 1.4.1

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 (494) hide show
  1. package/README.md +398 -773
  2. package/dist/components/index.d.ts +3 -0
  3. package/dist/components/index.d.ts.map +1 -0
  4. package/dist/components/index.js +5 -0
  5. package/dist/components/layouts/email_verification/config/email_verification_field_config.d.ts +23 -0
  6. package/dist/components/layouts/email_verification/config/email_verification_field_config.d.ts.map +1 -0
  7. package/dist/components/layouts/email_verification/config/email_verification_field_config.js +44 -0
  8. package/dist/components/layouts/email_verification/hooks/use_email_verification.d.ts +31 -0
  9. package/dist/components/layouts/email_verification/hooks/use_email_verification.d.ts.map +1 -0
  10. package/dist/components/layouts/email_verification/hooks/use_email_verification.js +222 -0
  11. package/dist/components/layouts/email_verification/index.d.ts +23 -0
  12. package/dist/components/layouts/email_verification/index.d.ts.map +1 -0
  13. package/dist/components/layouts/email_verification/index.js +61 -0
  14. package/dist/components/layouts/forgot_password/config/forgot_password_field_config.d.ts +10 -0
  15. package/dist/components/layouts/forgot_password/config/forgot_password_field_config.d.ts.map +1 -0
  16. package/dist/components/layouts/forgot_password/config/forgot_password_field_config.js +33 -0
  17. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts +22 -0
  18. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.d.ts.map +1 -0
  19. package/dist/components/layouts/forgot_password/hooks/use_forgot_password_form.js +127 -0
  20. package/dist/components/layouts/forgot_password/index.d.ts +18 -0
  21. package/dist/components/layouts/forgot_password/index.d.ts.map +1 -0
  22. package/dist/components/layouts/forgot_password/index.js +43 -0
  23. package/dist/components/layouts/index.d.ts +16 -0
  24. package/dist/components/layouts/index.d.ts.map +1 -0
  25. package/dist/components/layouts/index.js +11 -0
  26. package/dist/components/layouts/login/config/login_field_config.d.ts +11 -0
  27. package/dist/components/layouts/login/config/login_field_config.d.ts.map +1 -0
  28. package/dist/components/layouts/login/config/login_field_config.js +42 -0
  29. package/dist/components/layouts/login/hooks/use_login_form.d.ts +34 -0
  30. package/dist/components/layouts/login/hooks/use_login_form.d.ts.map +1 -0
  31. package/dist/components/layouts/login/hooks/use_login_form.js +196 -0
  32. package/dist/components/layouts/login/index.d.ts +31 -0
  33. package/dist/components/layouts/login/index.d.ts.map +1 -0
  34. package/dist/components/layouts/login/index.js +58 -0
  35. package/dist/components/layouts/my_settings/components/editable_field.d.ts +19 -0
  36. package/dist/components/layouts/my_settings/components/editable_field.d.ts.map +1 -0
  37. package/dist/components/layouts/my_settings/components/editable_field.js +73 -0
  38. package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts +28 -0
  39. package/dist/components/layouts/my_settings/components/password_change_dialog.d.ts.map +1 -0
  40. package/dist/components/layouts/my_settings/components/password_change_dialog.js +138 -0
  41. package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts +42 -0
  42. package/dist/components/layouts/my_settings/components/profile_picture_dialog.d.ts.map +1 -0
  43. package/dist/components/layouts/my_settings/components/profile_picture_dialog.js +198 -0
  44. package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts +16 -0
  45. package/dist/components/layouts/my_settings/components/profile_picture_display.d.ts.map +1 -0
  46. package/dist/components/layouts/my_settings/components/profile_picture_display.js +33 -0
  47. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts +17 -0
  48. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.d.ts.map +1 -0
  49. package/dist/components/layouts/my_settings/components/profile_picture_gravatar_tab.js +48 -0
  50. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts +21 -0
  51. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.d.ts.map +1 -0
  52. package/dist/components/layouts/my_settings/components/profile_picture_library_tab.js +144 -0
  53. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts +23 -0
  54. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.d.ts.map +1 -0
  55. package/dist/components/layouts/my_settings/components/profile_picture_upload_tab.js +169 -0
  56. package/dist/components/layouts/my_settings/config/my_settings_field_config.d.ts +19 -0
  57. package/dist/components/layouts/my_settings/config/my_settings_field_config.d.ts.map +1 -0
  58. package/dist/components/layouts/my_settings/config/my_settings_field_config.js +26 -0
  59. package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts +46 -0
  60. package/dist/components/layouts/my_settings/hooks/use_my_settings.d.ts.map +1 -0
  61. package/dist/components/layouts/my_settings/hooks/use_my_settings.js +354 -0
  62. package/dist/components/layouts/my_settings/index.d.ts +64 -0
  63. package/dist/components/layouts/my_settings/index.d.ts.map +1 -0
  64. package/dist/components/layouts/my_settings/index.js +65 -0
  65. package/dist/components/layouts/register/config/register_field_config.d.ts +14 -0
  66. package/dist/components/layouts/register/config/register_field_config.d.ts.map +1 -0
  67. package/dist/components/layouts/register/config/register_field_config.js +69 -0
  68. package/dist/components/layouts/register/hooks/use_register_form.d.ts +30 -0
  69. package/dist/components/layouts/register/hooks/use_register_form.d.ts.map +1 -0
  70. package/dist/components/layouts/register/hooks/use_register_form.js +184 -0
  71. package/dist/components/layouts/register/index.d.ts +23 -0
  72. package/dist/components/layouts/register/index.d.ts.map +1 -0
  73. package/dist/components/layouts/register/index.js +58 -0
  74. package/dist/components/layouts/reset_password/config/reset_password_field_config.d.ts +13 -0
  75. package/dist/components/layouts/reset_password/config/reset_password_field_config.d.ts.map +1 -0
  76. package/dist/components/layouts/reset_password/config/reset_password_field_config.js +53 -0
  77. package/dist/components/layouts/reset_password/hooks/use_reset_password_form.d.ts +28 -0
  78. package/dist/components/layouts/reset_password/hooks/use_reset_password_form.d.ts.map +1 -0
  79. package/dist/components/layouts/reset_password/hooks/use_reset_password_form.js +201 -0
  80. package/dist/components/layouts/reset_password/index.d.ts +23 -0
  81. package/dist/components/layouts/reset_password/index.d.ts.map +1 -0
  82. package/dist/components/layouts/reset_password/index.js +53 -0
  83. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts +20 -0
  84. package/dist/components/layouts/shared/components/already_logged_in_guard.d.ts.map +1 -0
  85. package/dist/components/layouts/shared/components/already_logged_in_guard.js +32 -0
  86. package/dist/components/layouts/shared/components/auth_page_shell.d.ts +7 -0
  87. package/dist/components/layouts/shared/components/auth_page_shell.d.ts.map +1 -0
  88. package/dist/components/layouts/shared/components/auth_page_shell.js +12 -0
  89. package/dist/components/layouts/shared/components/field_error_message.d.ts +7 -0
  90. package/dist/components/layouts/shared/components/field_error_message.d.ts.map +1 -0
  91. package/dist/components/layouts/shared/components/field_error_message.js +6 -0
  92. package/dist/components/layouts/shared/components/form_action_buttons.d.ts +14 -0
  93. package/dist/components/layouts/shared/components/form_action_buttons.d.ts.map +1 -0
  94. package/dist/components/layouts/shared/components/form_action_buttons.js +15 -0
  95. package/dist/components/layouts/shared/components/form_field_wrapper.d.ts +11 -0
  96. package/dist/components/layouts/shared/components/form_field_wrapper.d.ts.map +1 -0
  97. package/dist/components/layouts/shared/components/form_field_wrapper.js +9 -0
  98. package/dist/components/layouts/shared/components/form_header.d.ts +10 -0
  99. package/dist/components/layouts/shared/components/form_header.d.ts.map +1 -0
  100. package/dist/components/layouts/shared/components/form_header.js +5 -0
  101. package/dist/components/layouts/shared/components/logout_button.d.ts +7 -0
  102. package/dist/components/layouts/shared/components/logout_button.d.ts.map +1 -0
  103. package/dist/components/layouts/shared/components/logout_button.js +44 -0
  104. package/dist/components/layouts/shared/components/password_field.d.ts +13 -0
  105. package/dist/components/layouts/shared/components/password_field.d.ts.map +1 -0
  106. package/dist/components/layouts/shared/components/password_field.js +13 -0
  107. package/dist/components/layouts/shared/components/profile_pic_menu.d.ts +22 -0
  108. package/dist/components/layouts/shared/components/profile_pic_menu.d.ts.map +1 -0
  109. package/dist/components/layouts/shared/components/profile_pic_menu.js +169 -0
  110. package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts +12 -0
  111. package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.d.ts.map +1 -0
  112. package/dist/components/layouts/shared/components/profile_pic_menu_wrapper.js +16 -0
  113. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts +6 -0
  114. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.d.ts.map +1 -0
  115. package/dist/components/layouts/shared/components/sidebar_layout_wrapper.js +15 -0
  116. package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts +11 -0
  117. package/dist/components/layouts/shared/components/standalone_layout_wrapper.d.ts.map +1 -0
  118. package/dist/components/layouts/shared/components/standalone_layout_wrapper.js +10 -0
  119. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts +12 -0
  120. package/dist/components/layouts/shared/components/two_column_auth_layout.d.ts.map +1 -0
  121. package/dist/components/layouts/shared/components/two_column_auth_layout.js +8 -0
  122. package/dist/components/layouts/shared/components/unauthorized_guard.d.ts +14 -0
  123. package/dist/components/layouts/shared/components/unauthorized_guard.d.ts.map +1 -0
  124. package/dist/components/layouts/shared/components/unauthorized_guard.js +30 -0
  125. package/dist/components/layouts/shared/components/visual_panel.d.ts +9 -0
  126. package/dist/components/layouts/shared/components/visual_panel.d.ts.map +1 -0
  127. package/dist/components/layouts/shared/components/visual_panel.js +10 -0
  128. package/dist/components/layouts/shared/config/layout_customization.d.ts +38 -0
  129. package/dist/components/layouts/shared/config/layout_customization.d.ts.map +1 -0
  130. package/dist/components/layouts/shared/config/layout_customization.js +19 -0
  131. package/dist/components/layouts/shared/data/layout_data_client.d.ts +6 -0
  132. package/dist/components/layouts/shared/data/layout_data_client.d.ts.map +1 -0
  133. package/dist/components/layouts/shared/data/layout_data_client.js +9 -0
  134. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts +20 -0
  135. package/dist/components/layouts/shared/hooks/use_auth_status.d.ts.map +1 -0
  136. package/dist/components/layouts/shared/hooks/use_auth_status.js +71 -0
  137. package/dist/components/layouts/shared/hooks/use_hazo_auth.d.ts +48 -0
  138. package/dist/components/layouts/shared/hooks/use_hazo_auth.d.ts.map +1 -0
  139. package/dist/components/layouts/shared/hooks/use_hazo_auth.js +90 -0
  140. package/dist/components/layouts/shared/index.d.ts +24 -0
  141. package/dist/components/layouts/shared/index.d.ts.map +1 -0
  142. package/dist/components/layouts/shared/index.js +27 -0
  143. package/dist/components/layouts/shared/utils/ip_address.d.ts +7 -0
  144. package/dist/components/layouts/shared/utils/ip_address.d.ts.map +1 -0
  145. package/dist/components/layouts/shared/utils/ip_address.js +34 -0
  146. package/dist/components/layouts/shared/utils/validation.d.ts +15 -0
  147. package/dist/components/layouts/shared/utils/validation.d.ts.map +1 -0
  148. package/dist/components/layouts/shared/utils/validation.js +45 -0
  149. package/dist/components/layouts/user_management/components/roles_matrix.d.ts +29 -0
  150. package/dist/components/layouts/user_management/components/roles_matrix.d.ts.map +1 -0
  151. package/dist/components/layouts/user_management/components/roles_matrix.js +287 -0
  152. package/dist/components/layouts/user_management/index.d.ts +13 -0
  153. package/dist/components/layouts/user_management/index.d.ts.map +1 -0
  154. package/dist/components/layouts/user_management/index.js +495 -0
  155. package/dist/components/ui/alert-dialog.d.ts +21 -0
  156. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  157. package/dist/components/ui/alert-dialog.js +62 -0
  158. package/dist/components/ui/avatar.d.ts +7 -0
  159. package/dist/components/ui/avatar.d.ts.map +1 -0
  160. package/dist/components/ui/avatar.js +32 -0
  161. package/dist/components/ui/button.d.ts +12 -0
  162. package/dist/components/ui/button.d.ts.map +1 -0
  163. package/dist/components/ui/button.js +45 -0
  164. package/dist/components/ui/checkbox.d.ts +5 -0
  165. package/dist/components/ui/checkbox.d.ts.map +1 -0
  166. package/dist/components/ui/checkbox.js +23 -0
  167. package/dist/components/ui/dialog.d.ts +20 -0
  168. package/dist/components/ui/dialog.d.ts.map +1 -0
  169. package/dist/components/ui/dialog.js +52 -0
  170. package/dist/components/ui/dropdown-menu.d.ts +28 -0
  171. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  172. package/dist/components/ui/dropdown-menu.js +72 -0
  173. package/dist/components/ui/hazo_ui_tooltip.d.ts +26 -0
  174. package/dist/components/ui/hazo_ui_tooltip.d.ts.map +1 -0
  175. package/dist/components/ui/hazo_ui_tooltip.js +17 -0
  176. package/dist/components/ui/index.d.ts +20 -0
  177. package/dist/components/ui/index.d.ts.map +1 -0
  178. package/dist/components/ui/index.js +21 -0
  179. package/dist/components/ui/input.d.ts +4 -0
  180. package/dist/components/ui/input.d.ts.map +1 -0
  181. package/dist/components/ui/input.js +20 -0
  182. package/dist/components/ui/label.d.ts +6 -0
  183. package/dist/components/ui/label.d.ts.map +1 -0
  184. package/dist/components/ui/label.js +24 -0
  185. package/dist/components/ui/separator.d.ts +5 -0
  186. package/dist/components/ui/separator.d.ts.map +1 -0
  187. package/dist/components/ui/separator.js +22 -0
  188. package/dist/components/ui/sheet.d.ts +23 -0
  189. package/dist/components/ui/sheet.d.ts.map +1 -0
  190. package/dist/components/ui/sheet.js +66 -0
  191. package/dist/components/ui/sidebar.d.ts +66 -0
  192. package/dist/components/ui/sidebar.d.ts.map +1 -0
  193. package/dist/components/ui/sidebar.js +267 -0
  194. package/dist/components/ui/skeleton.d.ts +3 -0
  195. package/dist/components/ui/skeleton.d.ts.map +1 -0
  196. package/dist/components/ui/skeleton.js +18 -0
  197. package/dist/components/ui/sonner.d.ts +5 -0
  198. package/dist/components/ui/sonner.d.ts.map +1 -0
  199. package/dist/components/ui/sonner.js +28 -0
  200. package/dist/components/ui/switch.d.ts +5 -0
  201. package/dist/components/ui/switch.d.ts.map +1 -0
  202. package/dist/components/ui/switch.js +22 -0
  203. package/dist/components/ui/table.d.ts +11 -0
  204. package/dist/components/ui/table.d.ts.map +1 -0
  205. package/dist/components/ui/table.js +55 -0
  206. package/dist/components/ui/tabs.d.ts +8 -0
  207. package/dist/components/ui/tabs.d.ts.map +1 -0
  208. package/dist/components/ui/tabs.js +33 -0
  209. package/dist/components/ui/tooltip.d.ts +8 -0
  210. package/dist/components/ui/tooltip.d.ts.map +1 -0
  211. package/dist/components/ui/tooltip.js +25 -0
  212. package/dist/components/ui/vertical-tabs.d.ts +8 -0
  213. package/dist/components/ui/vertical-tabs.d.ts.map +1 -0
  214. package/dist/components/ui/vertical-tabs.js +37 -0
  215. package/dist/hooks/use-mobile.d.ts +2 -0
  216. package/dist/hooks/use-mobile.d.ts.map +1 -0
  217. package/dist/hooks/use-mobile.js +15 -0
  218. package/dist/index.d.ts +3 -0
  219. package/dist/index.d.ts.map +1 -0
  220. package/dist/index.js +5 -0
  221. package/dist/lib/already_logged_in_config.server.d.ts +14 -0
  222. package/dist/lib/already_logged_in_config.server.d.ts.map +1 -0
  223. package/dist/lib/already_logged_in_config.server.js +29 -0
  224. package/dist/lib/app_logger.d.ts +12 -0
  225. package/dist/lib/app_logger.d.ts.map +1 -0
  226. package/dist/lib/app_logger.js +14 -0
  227. package/dist/lib/auth/auth_cache.d.ts +83 -0
  228. package/dist/lib/auth/auth_cache.d.ts.map +1 -0
  229. package/dist/lib/auth/auth_cache.js +158 -0
  230. package/dist/lib/auth/auth_rate_limiter.d.ts +39 -0
  231. package/dist/lib/auth/auth_rate_limiter.d.ts.map +1 -0
  232. package/dist/lib/auth/auth_rate_limiter.js +95 -0
  233. package/dist/lib/auth/auth_types.d.ts +53 -0
  234. package/dist/lib/auth/auth_types.d.ts.map +1 -0
  235. package/dist/lib/auth/auth_types.js +16 -0
  236. package/dist/lib/auth/auth_utils.server.d.ts +47 -0
  237. package/dist/lib/auth/auth_utils.server.d.ts.map +1 -0
  238. package/dist/lib/auth/auth_utils.server.js +150 -0
  239. package/dist/lib/auth/hazo_get_auth.server.d.ts +12 -0
  240. package/dist/lib/auth/hazo_get_auth.server.d.ts.map +1 -0
  241. package/dist/lib/auth/hazo_get_auth.server.js +256 -0
  242. package/dist/lib/auth/index.d.ts +9 -0
  243. package/dist/lib/auth/index.d.ts.map +1 -0
  244. package/dist/lib/auth/index.js +12 -0
  245. package/dist/lib/auth/server_auth.d.ts +26 -0
  246. package/dist/lib/auth/server_auth.d.ts.map +1 -0
  247. package/dist/lib/auth/server_auth.js +62 -0
  248. package/dist/lib/auth_utility_config.server.d.ts +20 -0
  249. package/dist/lib/auth_utility_config.server.d.ts.map +1 -0
  250. package/dist/lib/auth_utility_config.server.js +64 -0
  251. package/dist/lib/config/config_loader.server.d.ts +44 -0
  252. package/dist/lib/config/config_loader.server.d.ts.map +1 -0
  253. package/dist/lib/config/config_loader.server.js +122 -0
  254. package/dist/lib/email_verification_config.server.d.ts +14 -0
  255. package/dist/lib/email_verification_config.server.d.ts.map +1 -0
  256. package/dist/lib/email_verification_config.server.js +20 -0
  257. package/dist/lib/file_types_config.server.d.ts +11 -0
  258. package/dist/lib/file_types_config.server.d.ts.map +1 -0
  259. package/dist/lib/file_types_config.server.js +16 -0
  260. package/dist/lib/forgot_password_config.server.d.ts +14 -0
  261. package/dist/lib/forgot_password_config.server.d.ts.map +1 -0
  262. package/dist/lib/forgot_password_config.server.js +20 -0
  263. package/dist/lib/hazo_connect_instance.server.d.ts +17 -0
  264. package/dist/lib/hazo_connect_instance.server.d.ts.map +1 -0
  265. package/dist/lib/hazo_connect_instance.server.js +88 -0
  266. package/dist/lib/hazo_connect_setup.d.ts +2 -0
  267. package/dist/lib/hazo_connect_setup.d.ts.map +1 -0
  268. package/dist/lib/hazo_connect_setup.js +49 -0
  269. package/dist/lib/hazo_connect_setup.server.d.ts +20 -0
  270. package/dist/lib/hazo_connect_setup.server.d.ts.map +1 -0
  271. package/dist/lib/hazo_connect_setup.server.js +138 -0
  272. package/dist/lib/index.d.ts +28 -0
  273. package/dist/lib/index.d.ts.map +1 -0
  274. package/dist/lib/index.js +35 -0
  275. package/dist/lib/login_config.server.d.ts +20 -0
  276. package/dist/lib/login_config.server.d.ts.map +1 -0
  277. package/dist/lib/login_config.server.js +37 -0
  278. package/dist/lib/messages_config.server.d.ts +13 -0
  279. package/dist/lib/messages_config.server.d.ts.map +1 -0
  280. package/dist/lib/messages_config.server.js +18 -0
  281. package/dist/lib/migrations/apply_migration.d.ts +22 -0
  282. package/dist/lib/migrations/apply_migration.d.ts.map +1 -0
  283. package/dist/lib/migrations/apply_migration.js +78 -0
  284. package/dist/lib/my_settings_config.server.d.ts +65 -0
  285. package/dist/lib/my_settings_config.server.d.ts.map +1 -0
  286. package/dist/lib/my_settings_config.server.js +67 -0
  287. package/dist/lib/password_requirements_config.server.d.ts +15 -0
  288. package/dist/lib/password_requirements_config.server.d.ts.map +1 -0
  289. package/dist/lib/password_requirements_config.server.js +26 -0
  290. package/dist/lib/profile_pic_menu_config.server.d.ts +26 -0
  291. package/dist/lib/profile_pic_menu_config.server.d.ts.map +1 -0
  292. package/dist/lib/profile_pic_menu_config.server.js +95 -0
  293. package/dist/lib/profile_picture_config.server.d.ts +16 -0
  294. package/dist/lib/profile_picture_config.server.d.ts.map +1 -0
  295. package/dist/lib/profile_picture_config.server.js +40 -0
  296. package/dist/lib/register_config.server.d.ts +24 -0
  297. package/dist/lib/register_config.server.d.ts.map +1 -0
  298. package/dist/lib/register_config.server.js +39 -0
  299. package/dist/lib/reset_password_config.server.d.ts +25 -0
  300. package/dist/lib/reset_password_config.server.d.ts.map +1 -0
  301. package/dist/lib/reset_password_config.server.js +38 -0
  302. package/dist/lib/services/email_service.d.ts +44 -0
  303. package/dist/lib/services/email_service.d.ts.map +1 -0
  304. package/dist/lib/services/email_service.js +480 -0
  305. package/dist/lib/services/email_verification_service.d.ts +35 -0
  306. package/dist/lib/services/email_verification_service.d.ts.map +1 -0
  307. package/dist/lib/services/email_verification_service.js +208 -0
  308. package/dist/lib/services/index.d.ts +13 -0
  309. package/dist/lib/services/index.d.ts.map +1 -0
  310. package/dist/lib/services/index.js +14 -0
  311. package/dist/lib/services/login_service.d.ts +20 -0
  312. package/dist/lib/services/login_service.d.ts.map +1 -0
  313. package/dist/lib/services/login_service.js +94 -0
  314. package/dist/lib/services/password_change_service.d.ts +19 -0
  315. package/dist/lib/services/password_change_service.d.ts.map +1 -0
  316. package/dist/lib/services/password_change_service.js +118 -0
  317. package/dist/lib/services/password_reset_service.d.ts +52 -0
  318. package/dist/lib/services/password_reset_service.d.ts.map +1 -0
  319. package/dist/lib/services/password_reset_service.js +318 -0
  320. package/dist/lib/services/profile_picture_remove_service.d.ts +15 -0
  321. package/dist/lib/services/profile_picture_remove_service.d.ts.map +1 -0
  322. package/dist/lib/services/profile_picture_remove_service.js +94 -0
  323. package/dist/lib/services/profile_picture_service.d.ts +45 -0
  324. package/dist/lib/services/profile_picture_service.d.ts.map +1 -0
  325. package/dist/lib/services/profile_picture_service.js +183 -0
  326. package/dist/lib/services/profile_picture_source_mapper.d.ts +23 -0
  327. package/dist/lib/services/profile_picture_source_mapper.d.ts.map +1 -0
  328. package/dist/lib/services/profile_picture_source_mapper.js +45 -0
  329. package/dist/lib/services/registration_service.d.ts +20 -0
  330. package/dist/lib/services/registration_service.d.ts.map +1 -0
  331. package/dist/lib/services/registration_service.js +147 -0
  332. package/dist/lib/services/token_service.d.ts +20 -0
  333. package/dist/lib/services/token_service.d.ts.map +1 -0
  334. package/dist/lib/services/token_service.js +201 -0
  335. package/dist/lib/services/user_profiles_service.d.ts +31 -0
  336. package/dist/lib/services/user_profiles_service.d.ts.map +1 -0
  337. package/dist/lib/services/user_profiles_service.js +99 -0
  338. package/dist/lib/services/user_update_service.d.ts +23 -0
  339. package/dist/lib/services/user_update_service.d.ts.map +1 -0
  340. package/dist/lib/services/user_update_service.js +103 -0
  341. package/dist/lib/ui_shell_config.server.d.ts +16 -0
  342. package/dist/lib/ui_shell_config.server.d.ts.map +1 -0
  343. package/dist/lib/ui_shell_config.server.js +28 -0
  344. package/dist/lib/ui_sizes_config.server.d.ts +17 -0
  345. package/dist/lib/ui_sizes_config.server.d.ts.map +1 -0
  346. package/dist/lib/ui_sizes_config.server.js +22 -0
  347. package/dist/lib/user_fields_config.server.d.ts +13 -0
  348. package/dist/lib/user_fields_config.server.d.ts.map +1 -0
  349. package/dist/lib/user_fields_config.server.js +21 -0
  350. package/dist/lib/user_management_config.server.d.ts +10 -0
  351. package/dist/lib/user_management_config.server.d.ts.map +1 -0
  352. package/dist/lib/user_management_config.server.js +26 -0
  353. package/dist/lib/utils/api_route_helpers.d.ts +13 -0
  354. package/dist/lib/utils/api_route_helpers.d.ts.map +1 -0
  355. package/dist/lib/utils/api_route_helpers.js +58 -0
  356. package/dist/lib/utils/error_sanitizer.d.ts +16 -0
  357. package/dist/lib/utils/error_sanitizer.d.ts.map +1 -0
  358. package/dist/lib/utils/error_sanitizer.js +39 -0
  359. package/dist/lib/utils.d.ts +4 -0
  360. package/dist/lib/utils.d.ts.map +1 -0
  361. package/dist/lib/utils.js +9 -0
  362. package/dist/server/config/config_loader.d.ts +26 -0
  363. package/dist/server/config/config_loader.d.ts.map +1 -0
  364. package/dist/server/config/config_loader.js +329 -0
  365. package/dist/server/index.d.ts +2 -0
  366. package/dist/server/index.d.ts.map +1 -0
  367. package/dist/server/index.js +32 -0
  368. package/dist/server/logging/logger_service.d.ts +3 -0
  369. package/dist/server/logging/logger_service.d.ts.map +1 -0
  370. package/dist/server/logging/logger_service.js +37 -0
  371. package/dist/server/routes/root_router.d.ts +3 -0
  372. package/dist/server/routes/root_router.d.ts.map +1 -0
  373. package/dist/server/routes/root_router.js +14 -0
  374. package/dist/server/server.d.ts +3 -0
  375. package/dist/server/server.d.ts.map +1 -0
  376. package/dist/server/server.js +25 -0
  377. package/dist/server/types/app_types.d.ts +53 -0
  378. package/dist/server/types/app_types.d.ts.map +1 -0
  379. package/dist/server/types/app_types.js +1 -0
  380. package/migrations/003_add_url_on_logon_to_hazo_users.sql +8 -0
  381. package/next.config.mjs +12 -0
  382. package/package.json +150 -1
  383. package/src/components/index.ts +7 -0
  384. package/src/components/layouts/email_verification/config/email_verification_field_config.ts +2 -2
  385. package/src/components/layouts/email_verification/hooks/use_email_verification.ts +3 -3
  386. package/src/components/layouts/email_verification/index.tsx +11 -11
  387. package/src/components/layouts/forgot_password/config/forgot_password_field_config.ts +2 -2
  388. package/src/components/layouts/forgot_password/hooks/use_forgot_password_form.ts +3 -3
  389. package/src/components/layouts/forgot_password/index.tsx +10 -10
  390. package/src/components/layouts/index.ts +26 -0
  391. package/src/components/layouts/login/config/login_field_config.ts +2 -2
  392. package/src/components/layouts/login/hooks/use_login_form.ts +5 -5
  393. package/src/components/layouts/login/index.tsx +11 -11
  394. package/src/components/layouts/my_settings/components/editable_field.tsx +3 -3
  395. package/src/components/layouts/my_settings/components/password_change_dialog.tsx +5 -5
  396. package/src/components/layouts/my_settings/components/profile_picture_dialog.tsx +7 -7
  397. package/src/components/layouts/my_settings/components/profile_picture_display.tsx +2 -2
  398. package/src/components/layouts/my_settings/components/profile_picture_gravatar_tab.tsx +3 -3
  399. package/src/components/layouts/my_settings/components/profile_picture_library_tab.tsx +5 -5
  400. package/src/components/layouts/my_settings/components/profile_picture_upload_tab.tsx +4 -4
  401. package/src/components/layouts/my_settings/config/my_settings_field_config.ts +2 -2
  402. package/src/components/layouts/my_settings/hooks/use_my_settings.ts +2 -2
  403. package/src/components/layouts/my_settings/index.tsx +10 -10
  404. package/src/components/layouts/register/config/register_field_config.ts +2 -2
  405. package/src/components/layouts/register/hooks/use_register_form.ts +4 -4
  406. package/src/components/layouts/register/index.tsx +11 -11
  407. package/src/components/layouts/reset_password/config/reset_password_field_config.ts +2 -2
  408. package/src/components/layouts/reset_password/hooks/use_reset_password_form.ts +4 -4
  409. package/src/components/layouts/reset_password/index.tsx +10 -10
  410. package/src/components/layouts/shared/components/already_logged_in_guard.tsx +4 -4
  411. package/src/components/layouts/shared/components/auth_page_shell.tsx +3 -3
  412. package/src/components/layouts/shared/components/form_action_buttons.tsx +2 -2
  413. package/src/components/layouts/shared/components/form_field_wrapper.tsx +2 -2
  414. package/src/components/layouts/shared/components/logout_button.tsx +2 -2
  415. package/src/components/layouts/shared/components/password_field.tsx +3 -3
  416. package/src/components/layouts/shared/components/profile_pic_menu.tsx +5 -5
  417. package/src/components/layouts/shared/components/profile_pic_menu_wrapper.tsx +2 -2
  418. package/src/components/layouts/shared/components/sidebar_layout_wrapper.tsx +3 -3
  419. package/src/components/layouts/shared/components/standalone_layout_wrapper.tsx +1 -1
  420. package/src/components/layouts/shared/components/two_column_auth_layout.tsx +1 -1
  421. package/src/components/layouts/shared/components/unauthorized_guard.tsx +2 -2
  422. package/src/components/layouts/shared/hooks/use_hazo_auth.ts +1 -1
  423. package/src/components/layouts/shared/index.ts +34 -0
  424. package/src/components/layouts/shared/utils/validation.ts +1 -1
  425. package/src/components/layouts/user_management/components/roles_matrix.tsx +7 -7
  426. package/src/components/layouts/user_management/index.tsx +11 -11
  427. package/src/components/ui/alert-dialog.tsx +2 -2
  428. package/src/components/ui/avatar.tsx +1 -1
  429. package/src/components/ui/button.tsx +1 -1
  430. package/src/components/ui/checkbox.tsx +1 -1
  431. package/src/components/ui/dialog.tsx +1 -1
  432. package/src/components/ui/dropdown-menu.tsx +1 -1
  433. package/src/components/ui/hazo_ui_tooltip.tsx +1 -1
  434. package/src/components/ui/index.ts +22 -0
  435. package/src/components/ui/input.tsx +1 -1
  436. package/src/components/ui/label.tsx +1 -1
  437. package/src/components/ui/separator.tsx +1 -1
  438. package/src/components/ui/sheet.tsx +1 -1
  439. package/src/components/ui/sidebar.tsx +8 -8
  440. package/src/components/ui/skeleton.tsx +1 -1
  441. package/src/components/ui/switch.tsx +1 -1
  442. package/src/components/ui/table.tsx +1 -1
  443. package/src/components/ui/tabs.tsx +1 -1
  444. package/src/components/ui/tooltip.tsx +1 -1
  445. package/src/components/ui/vertical-tabs.tsx +1 -1
  446. package/src/index.ts +7 -0
  447. package/src/lib/already_logged_in_config.server.ts +1 -1
  448. package/src/lib/app_logger.ts +1 -1
  449. package/src/lib/auth/auth_cache.ts +1 -1
  450. package/src/lib/auth/auth_utils.server.ts +2 -2
  451. package/src/lib/auth/hazo_get_auth.server.ts +8 -8
  452. package/src/lib/auth/index.ts +23 -0
  453. package/src/lib/auth/server_auth.ts +2 -2
  454. package/src/lib/auth_utility_config.server.ts +1 -1
  455. package/src/lib/config/config_loader.server.ts +1 -1
  456. package/src/lib/email_verification_config.server.ts +1 -1
  457. package/src/lib/file_types_config.server.ts +1 -1
  458. package/src/lib/forgot_password_config.server.ts +1 -1
  459. package/src/lib/hazo_connect_instance.server.ts +2 -2
  460. package/src/lib/hazo_connect_setup.server.ts +2 -2
  461. package/src/lib/index.ts +44 -0
  462. package/src/lib/login_config.server.ts +2 -2
  463. package/src/lib/messages_config.server.ts +1 -1
  464. package/src/lib/my_settings_config.server.ts +7 -7
  465. package/src/lib/password_requirements_config.server.ts +1 -1
  466. package/src/lib/profile_pic_menu_config.server.ts +1 -1
  467. package/src/lib/profile_picture_config.server.ts +2 -2
  468. package/src/lib/register_config.server.ts +4 -4
  469. package/src/lib/reset_password_config.server.ts +3 -3
  470. package/src/lib/services/email_service.ts +2 -2
  471. package/src/lib/services/email_verification_service.ts +3 -3
  472. package/src/lib/services/index.ts +15 -0
  473. package/src/lib/services/login_service.ts +3 -3
  474. package/src/lib/services/password_change_service.ts +3 -3
  475. package/src/lib/services/password_reset_service.ts +3 -3
  476. package/src/lib/services/profile_picture_remove_service.ts +3 -3
  477. package/src/lib/services/profile_picture_service.ts +5 -5
  478. package/src/lib/services/registration_service.ts +8 -8
  479. package/src/lib/services/token_service.ts +2 -2
  480. package/src/lib/services/user_profiles_service.ts +2 -2
  481. package/src/lib/services/user_update_service.ts +4 -4
  482. package/src/lib/ui_shell_config.server.ts +1 -1
  483. package/src/lib/ui_sizes_config.server.ts +1 -1
  484. package/src/lib/user_fields_config.server.ts +1 -1
  485. package/src/lib/user_management_config.server.ts +1 -2
  486. package/src/lib/utils/error_sanitizer.ts +1 -1
  487. package/src/routes/index.ts +34 -0
  488. package/src/server/config/config_loader.ts +2 -2
  489. package/src/server/index.ts +2 -2
  490. package/src/server/logging/logger_service.ts +1 -1
  491. package/src/server/server.ts +2 -2
  492. package/src/server/types/express.d.ts +1 -1
  493. package/tsconfig.build.json +39 -0
  494. package/tsconfig.json +5 -1
package/README.md CHANGED
@@ -2,36 +2,118 @@
2
2
 
3
3
  A reusable authentication UI component package powered by Next.js, TailwindCSS, and shadcn. It integrates `hazo_config` for configuration management and `hazo_connect` for data access, enabling future components to stay aligned with platform conventions.
4
4
 
5
- ### Installation
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Quick Start](#quick-start)
9
+ - [Configuration Setup](#configuration-setup)
10
+ - [Database Setup](#database-setup)
11
+ - [Using Components](#using-components)
12
+ - [Authentication Service](#authentication-service)
13
+ - [Profile Picture Menu Widget](#profile-picture-menu-widget)
14
+ - [User Profile Service](#user-profile-service)
15
+ - [Local Development](#local-development)
16
+
17
+ ---
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install hazo_auth
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Install the package
6
30
 
7
31
  ```bash
8
32
  npm install hazo_auth
9
33
  ```
10
34
 
11
- ### Configuration Setup
35
+ ### 2. Copy configuration files
36
+
37
+ ```bash
38
+ cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
39
+ cp node_modules/hazo_auth/hazo_notify_config.example.ini ./hazo_notify_config.ini
40
+ ```
41
+
42
+ ### 3. Set up environment variables
43
+
44
+ Create a `.env.local` file:
45
+
46
+ ```env
47
+ ZEPTOMAIL_API_KEY=your_api_key_here
48
+ ```
49
+
50
+ ### 4. Set up the database
51
+
52
+ Run the database setup SQL script (see [Database Setup](#database-setup)).
53
+
54
+ ### 5. Import and use components
55
+
56
+ ```typescript
57
+ // Import layout components
58
+ import { LoginLayout } from "hazo_auth/components/layouts/login";
59
+ import { RegisterLayout } from "hazo_auth/components/layouts/register";
60
+
61
+ // Import UI components
62
+ import { Button } from "hazo_auth/components/ui/button";
63
+ import { Input } from "hazo_auth/components/ui/input";
64
+
65
+ // Import shared components and hooks (recommended - uses barrel exports)
66
+ import {
67
+ ProfilePicMenu,
68
+ ProfilePicMenuWrapper,
69
+ use_hazo_auth,
70
+ use_auth_status
71
+ } from "hazo_auth/components/layouts/shared";
72
+
73
+ // OR import hooks directly
74
+ import { use_hazo_auth } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
75
+ import { use_auth_status } from "hazo_auth/components/layouts/shared/hooks/use_auth_status";
76
+
77
+ // Import server-side utilities
78
+ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
79
+ import { get_authenticated_user } from "hazo_auth/lib/auth/auth_utils.server";
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Configuration Setup
12
85
 
13
86
  After installing the package, you need to set up configuration files in your project root:
14
87
 
15
- 1. **Copy the example config files to your project root:**
16
- ```bash
17
- cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
18
- cp node_modules/hazo_auth/hazo_notify_config.example.ini ./hazo_notify_config.ini
19
- ```
88
+ ### 1. Copy the example config files to your project root:
89
+
90
+ ```bash
91
+ cp node_modules/hazo_auth/hazo_auth_config.example.ini ./hazo_auth_config.ini
92
+ cp node_modules/hazo_auth/hazo_notify_config.example.ini ./hazo_notify_config.ini
93
+ ```
94
+
95
+ ### 2. Customize the configuration files:
96
+
97
+ - Edit `hazo_auth_config.ini` to configure authentication settings, database connection, UI labels, and more
98
+ - Edit `hazo_notify_config.ini` to configure email service settings (Zeptomail, SMTP, etc.)
20
99
 
21
- 2. **Customize the configuration files:**
22
- - Edit `hazo_auth_config.ini` to configure authentication settings, database connection, UI labels, and more
23
- - Edit `hazo_notify_config.ini` to configure email service settings (Zeptomail, SMTP, etc.)
100
+ ### 3. Set up environment variables (recommended for sensitive data):
24
101
 
25
- 3. **Set up environment variables (recommended for sensitive data):**
26
- - Create a `.env.local` file in your project root
27
- - Add `ZEPTOMAIL_API_KEY=your_api_key_here` (if using Zeptomail)
28
- - Add other sensitive configuration values as needed
102
+ - Create a `.env.local` file in your project root
103
+ - Add `ZEPTOMAIL_API_KEY=your_api_key_here` (if using Zeptomail)
104
+ - Add other sensitive configuration values as needed
29
105
 
30
106
  **Important:** The configuration files must be located in your project root directory (where `process.cwd()` points to), not inside `node_modules`. The package reads configuration from `process.cwd()` at runtime, so storing them elsewhere (including `node_modules/hazo_auth`) will break runtime access.
31
107
 
32
- ### Database Setup
108
+ ---
109
+
110
+ ## Database Setup
111
+
112
+ Before using `hazo_auth`, you need to create the required database tables. The package supports both **PostgreSQL** (for production) and **SQLite** (for local development/testing).
33
113
 
34
- Before using `hazo_auth`, you need to create the required database tables. Run the following SQL scripts in your PostgreSQL database:
114
+ ### PostgreSQL Setup
115
+
116
+ Run the following SQL scripts in your PostgreSQL database:
35
117
 
36
118
  #### 1. Create the Profile Source Enum Type
37
119
 
@@ -65,6 +147,8 @@ CREATE TABLE hazo_users (
65
147
  CREATE INDEX idx_hazo_users_email ON hazo_users(email_address);
66
148
  ```
67
149
 
150
+ **Note:** The `url_on_logon` field is used to store a custom redirect URL for users after successful login. This allows per-user customization of post-login navigation.
151
+
68
152
  #### 3. Create the Refresh Tokens Table
69
153
 
70
154
  ```sql
@@ -88,7 +172,7 @@ CREATE INDEX idx_hazo_refresh_tokens_token_type ON hazo_refresh_tokens(token_typ
88
172
  ```sql
89
173
  -- Permissions table for RBAC
90
174
  CREATE TABLE hazo_permissions (
91
- id SERIAL PRIMARY KEY,
175
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
92
176
  permission_name TEXT NOT NULL UNIQUE,
93
177
  description TEXT,
94
178
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
@@ -101,7 +185,7 @@ CREATE TABLE hazo_permissions (
101
185
  ```sql
102
186
  -- Roles table for RBAC
103
187
  CREATE TABLE hazo_roles (
104
- id SERIAL PRIMARY KEY,
188
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
105
189
  role_name TEXT NOT NULL UNIQUE,
106
190
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
107
191
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
@@ -113,8 +197,8 @@ CREATE TABLE hazo_roles (
113
197
  ```sql
114
198
  -- Junction table linking roles to permissions
115
199
  CREATE TABLE hazo_role_permissions (
116
- role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
117
- permission_id INTEGER NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
200
+ role_id UUID NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
201
+ permission_id UUID NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
118
202
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
119
203
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
120
204
  PRIMARY KEY (role_id, permission_id)
@@ -131,7 +215,7 @@ CREATE INDEX idx_hazo_role_permissions_permission_id ON hazo_role_permissions(pe
131
215
  -- Junction table linking users to roles
132
216
  CREATE TABLE hazo_user_roles (
133
217
  user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
134
- role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
218
+ role_id UUID NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
135
219
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
136
220
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
137
221
  PRIMARY KEY (user_id, role_id)
@@ -142,13 +226,13 @@ CREATE INDEX idx_hazo_user_roles_user_id ON hazo_user_roles(user_id);
142
226
  CREATE INDEX idx_hazo_user_roles_role_id ON hazo_user_roles(role_id);
143
227
  ```
144
228
 
145
- #### Complete Setup Script
229
+ ### Complete PostgreSQL Setup Script
146
230
 
147
231
  For convenience, here's the complete SQL script to create all tables at once:
148
232
 
149
233
  ```sql
150
234
  -- ============================================
151
- -- hazo_auth Database Setup Script
235
+ -- hazo_auth Database Setup Script (PostgreSQL)
152
236
  -- ============================================
153
237
 
154
238
  -- 1. Create enum type
@@ -187,7 +271,7 @@ CREATE INDEX idx_hazo_refresh_tokens_token_type ON hazo_refresh_tokens(token_typ
187
271
 
188
272
  -- 4. Create permissions table
189
273
  CREATE TABLE hazo_permissions (
190
- id SERIAL PRIMARY KEY,
274
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
191
275
  permission_name TEXT NOT NULL UNIQUE,
192
276
  description TEXT,
193
277
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
@@ -196,7 +280,7 @@ CREATE TABLE hazo_permissions (
196
280
 
197
281
  -- 5. Create roles table
198
282
  CREATE TABLE hazo_roles (
199
- id SERIAL PRIMARY KEY,
283
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
200
284
  role_name TEXT NOT NULL UNIQUE,
201
285
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
202
286
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
@@ -204,8 +288,8 @@ CREATE TABLE hazo_roles (
204
288
 
205
289
  -- 6. Create role-permissions junction table
206
290
  CREATE TABLE hazo_role_permissions (
207
- role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
208
- permission_id INTEGER NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
291
+ role_id UUID NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
292
+ permission_id UUID NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
209
293
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
210
294
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
211
295
  PRIMARY KEY (role_id, permission_id)
@@ -216,7 +300,7 @@ CREATE INDEX idx_hazo_role_permissions_permission_id ON hazo_role_permissions(pe
216
300
  -- 7. Create user-roles junction table
217
301
  CREATE TABLE hazo_user_roles (
218
302
  user_id UUID NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
219
- role_id INTEGER NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
303
+ role_id UUID NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
220
304
  created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
221
305
  changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
222
306
  PRIMARY KEY (user_id, role_id)
@@ -225,7 +309,80 @@ CREATE INDEX idx_hazo_user_roles_user_id ON hazo_user_roles(user_id);
225
309
  CREATE INDEX idx_hazo_user_roles_role_id ON hazo_user_roles(role_id);
226
310
  ```
227
311
 
228
- #### Initialize Default Permissions and Super User
312
+ ### SQLite Setup (for local development)
313
+
314
+ For local development and testing, you can use SQLite. The SQLite schema is slightly different (no UUID type, TEXT used instead):
315
+
316
+ ```sql
317
+ -- ============================================
318
+ -- hazo_auth Database Setup Script (SQLite)
319
+ -- ============================================
320
+
321
+ -- Users table
322
+ CREATE TABLE IF NOT EXISTS hazo_users (
323
+ id TEXT PRIMARY KEY,
324
+ email_address TEXT NOT NULL UNIQUE,
325
+ password_hash TEXT NOT NULL,
326
+ name TEXT,
327
+ email_verified INTEGER NOT NULL DEFAULT 0,
328
+ is_active INTEGER NOT NULL DEFAULT 1,
329
+ login_attempts INTEGER NOT NULL DEFAULT 0,
330
+ last_logon TEXT,
331
+ profile_picture_url TEXT,
332
+ profile_source TEXT,
333
+ mfa_secret TEXT,
334
+ url_on_logon TEXT,
335
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
336
+ changed_at TEXT NOT NULL DEFAULT (datetime('now'))
337
+ );
338
+
339
+ -- Refresh tokens table
340
+ CREATE TABLE IF NOT EXISTS hazo_refresh_tokens (
341
+ id TEXT PRIMARY KEY,
342
+ user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
343
+ token_hash TEXT NOT NULL,
344
+ token_type TEXT NOT NULL,
345
+ expires_at TEXT NOT NULL,
346
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
347
+ );
348
+
349
+ -- Permissions table
350
+ CREATE TABLE IF NOT EXISTS hazo_permissions (
351
+ id TEXT PRIMARY KEY,
352
+ permission_name TEXT NOT NULL UNIQUE,
353
+ description TEXT,
354
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
355
+ changed_at TEXT NOT NULL DEFAULT (datetime('now'))
356
+ );
357
+
358
+ -- Roles table
359
+ CREATE TABLE IF NOT EXISTS hazo_roles (
360
+ id TEXT PRIMARY KEY,
361
+ role_name TEXT NOT NULL UNIQUE,
362
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
363
+ changed_at TEXT NOT NULL DEFAULT (datetime('now'))
364
+ );
365
+
366
+ -- Role-permissions junction table
367
+ CREATE TABLE IF NOT EXISTS hazo_role_permissions (
368
+ role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
369
+ permission_id TEXT NOT NULL REFERENCES hazo_permissions(id) ON DELETE CASCADE,
370
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
371
+ changed_at TEXT NOT NULL DEFAULT (datetime('now')),
372
+ PRIMARY KEY (role_id, permission_id)
373
+ );
374
+
375
+ -- User-roles junction table
376
+ CREATE TABLE IF NOT EXISTS hazo_user_roles (
377
+ user_id TEXT NOT NULL REFERENCES hazo_users(id) ON DELETE CASCADE,
378
+ role_id TEXT NOT NULL REFERENCES hazo_roles(id) ON DELETE CASCADE,
379
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
380
+ changed_at TEXT NOT NULL DEFAULT (datetime('now')),
381
+ PRIMARY KEY (user_id, role_id)
382
+ );
383
+ ```
384
+
385
+ ### Initialize Default Permissions and Super User
229
386
 
230
387
  After creating the tables, you can use the `init-users` script to set up default permissions and a super user:
231
388
 
@@ -238,67 +395,90 @@ This script reads from `hazo_auth_config.ini` and:
238
395
  2. Creates a `default_super_user_role` role with all permissions
239
396
  3. Assigns the role to the user specified in `default_super_user_email`
240
397
 
241
- ### Expose hazo_auth Routes in the Consumer App
398
+ ### Apply Migrations
242
399
 
243
- Because `src/app/hazo_auth` (pages) and `src/app/api/hazo_auth` (API routes) need to be part of the consuming Next.js app’s routing tree, make sure they exist in your project’s `src/app` directory. Two recommended approaches:
400
+ To apply database migrations (e.g., adding new fields):
244
401
 
245
- 1. **Create symlinks (preferred during development):**
246
- ```bash
247
- mkdir -p src/app/api src/app
248
- ln -s ../../node_modules/hazo_auth/src/app/api/hazo_auth src/app/api/hazo_auth
249
- ln -s ../../node_modules/hazo_auth/src/app/hazo_auth src/app/hazo_auth
250
- ```
251
- Adjust the relative paths if your project structure differs.
402
+ ```bash
403
+ # Apply a specific migration
404
+ npx tsx scripts/apply_migration.ts migrations/003_add_url_on_logon_to_hazo_users.sql
252
405
 
253
- 2. **Copy the directories (useful for deployment or when symlinks cause issues):**
254
- ```bash
255
- cp -R node_modules/hazo_auth/src/app/api/hazo_auth src/app/api/hazo_auth
256
- cp -R node_modules/hazo_auth/src/app/hazo_auth src/app/hazo_auth
257
- ```
258
- Add an npm script (e.g., `postinstall`) to automate copying after installations or updates.
406
+ # Or apply all pending migrations
407
+ npx tsx scripts/apply_migration.ts
408
+ ```
259
409
 
260
- > The package expects these routes to live at `src/app/api/hazo_auth` and `src/app/hazo_auth` inside the consumer project. Without copying or linking them, Next.js won’t mount the auth pages or APIs.
410
+ ---
261
411
 
262
- ### Choose the UI Shell (Test Sidebar vs Standalone)
412
+ ## Using Components
263
413
 
264
- By default, the pages render inside the “test workspace” sidebar so you can quickly preview every flow. When you reuse the routes inside another project you’ll usually want a clean, standalone wrapper instead. Set this in `hazo_auth_config.ini`:
414
+ ### Package Exports
265
415
 
266
- ```ini
267
- [hazo_auth__ui_shell]
268
- # Options: test_sidebar | standalone
269
- layout_mode = standalone
270
- # Optional tweaks for the standalone header wrapper/classes:
271
- # standalone_heading = Welcome back
272
- # standalone_description = Your description here
273
- # standalone_wrapper_class = min-h-screen bg-background py-8
274
- # standalone_content_class = mx-auto w-full max-w-4xl rounded-2xl border bg-card
275
- ```
416
+ The package exports components through these paths:
276
417
 
277
- - `test_sidebar`: keeps the developer sidebar (perfect for the demo workspace or Storybook screenshots).
278
- - `standalone`: renders the page body directly so it inherits your own app shell, layout, and theme tokens.
279
- - The wrapper and content class overrides let you align spacing/borders with your design system without editing package code.
418
+ ```typescript
419
+ // Main entry point - exports all public APIs
420
+ import { ... } from "hazo_auth";
421
+
422
+ // Layout components
423
+ import { LoginLayout } from "hazo_auth/components/layouts/login";
424
+ import { RegisterLayout } from "hazo_auth/components/layouts/register";
425
+ import { ForgotPasswordLayout } from "hazo_auth/components/layouts/forgot_password";
426
+ import { ResetPasswordLayout } from "hazo_auth/components/layouts/reset_password";
427
+ import { EmailVerificationLayout } from "hazo_auth/components/layouts/verify_email";
428
+ import { MySettingsLayout } from "hazo_auth/components/layouts/my_settings";
429
+ import { UserManagementLayout } from "hazo_auth/components/layouts/user_management";
430
+
431
+ // UI components
432
+ import { Button } from "hazo_auth/components/ui/button";
433
+ import { Input } from "hazo_auth/components/ui/input";
434
+ import { Avatar } from "hazo_auth/components/ui/avatar";
435
+ // ... and more shadcn-based components
436
+
437
+ // Shared layout components and hooks (barrel import - recommended)
438
+ import {
439
+ ProfilePicMenu,
440
+ ProfilePicMenuWrapper,
441
+ FormActionButtons,
442
+ use_hazo_auth,
443
+ use_auth_status
444
+ } from "hazo_auth/components/layouts/shared";
445
+
446
+ // OR import individual components directly
447
+ import { ProfilePicMenu } from "hazo_auth/components/layouts/shared/components/profile_pic_menu";
448
+ import { ProfilePicMenuWrapper } from "hazo_auth/components/layouts/shared/components/profile_pic_menu_wrapper";
449
+ import { FormActionButtons } from "hazo_auth/components/layouts/shared/components/form_action_buttons";
450
+
451
+ // OR import hooks directly
452
+ import { use_hazo_auth } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
453
+ import { use_auth_status } from "hazo_auth/components/layouts/shared/hooks/use_auth_status";
454
+
455
+ // Library utilities
456
+ import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
457
+ import { get_authenticated_user } from "hazo_auth/lib/auth/auth_utils.server";
458
+ import { get_server_auth_user } from "hazo_auth/lib/auth/server_auth";
280
459
 
281
- Every route (`/hazo_auth/login`, `/hazo_auth/register`, etc.) automatically looks at this config, so switching modes is instant.
460
+ // Server utilities
461
+ import { get_hazo_connect_instance } from "hazo_auth/server/hazo_connect_instance.server";
462
+ ```
282
463
 
283
- ### Using Just the Layout Components
464
+ ### Using Layout Components
284
465
 
285
- Prefer to drop the forms into your own routes without copying the provided pages? Import the layouts directly and feed them a `data_client` plus any label/button overrides:
466
+ Prefer to drop the forms into your own routes without using the pre-built pages? Import the layouts directly and feed them a `data_client` plus any label/button overrides:
286
467
 
287
468
  ```tsx
288
469
  // app/(auth)/login/page.tsx in your project
289
- import login_layout from "hazo_auth/components/layouts/login";
290
- import { createLayoutDataClient } from "hazo_auth/components/layouts/shared/data/layout_data_client";
291
- import { create_sqlite_hazo_connect } from "hazo_auth/lib/hazo_connect_setup";
470
+ import { LoginLayout, createLayoutDataClient } from "hazo_auth";
471
+ import { create_postgrest_hazo_connect } from "hazo_auth/lib/hazo_connect_setup";
292
472
 
293
473
  export default async function LoginPage() {
294
- const hazoConnect = create_sqlite_hazo_connect();
474
+ const hazoConnect = create_postgrest_hazo_connect();
295
475
  const dataClient = createLayoutDataClient(hazoConnect);
296
- const LoginLayout = login_layout;
297
476
 
298
477
  return (
299
478
  <div className="my-app-shell">
300
479
  <LoginLayout
301
480
  image_src="/marketing/login-hero.svg"
481
+ image_alt="Login hero image"
302
482
  data_client={dataClient}
303
483
  redirectRoute="/dashboard"
304
484
  />
@@ -307,7 +487,40 @@ export default async function LoginPage() {
307
487
  }
308
488
  ```
309
489
 
310
- The same import pattern works for every layout under `components/layouts/*`, so you can mix-and-match pieces (profile picture dialog, password field, etc.) wherever you need them.
490
+ **Available Layout Components:**
491
+ - `LoginLayout` - Login form with email/password
492
+ - `RegisterLayout` - Registration form with password requirements
493
+ - `ForgotPasswordLayout` - Request password reset
494
+ - `ResetPasswordLayout` - Set new password with token
495
+ - `EmailVerificationLayout` - Verify email address
496
+ - `MySettingsLayout` - User profile and settings
497
+ - `UserManagementLayout` - Admin user/role management
498
+
499
+ **Shared Components:**
500
+ - `ProfilePicMenu` / `ProfilePicMenuWrapper` - Navbar profile menu
501
+ - `FormActionButtons`, `FormFieldWrapper`, `PasswordField`
502
+ - And more under `hazo_auth/components/layouts/shared/`
503
+
504
+ ### Choose the UI Shell (Test Sidebar vs Standalone)
505
+
506
+ By default, the pages render inside the "test workspace" sidebar so you can quickly preview every flow. When you reuse the routes inside another project you'll usually want a clean, standalone wrapper instead. Set this in `hazo_auth_config.ini`:
507
+
508
+ ```ini
509
+ [hazo_auth__ui_shell]
510
+ # Options: test_sidebar | standalone
511
+ layout_mode = standalone
512
+ # Optional tweaks for the standalone header wrapper/classes:
513
+ # standalone_heading = Welcome back
514
+ # standalone_description = Your description here
515
+ # standalone_wrapper_class = min-h-screen bg-background py-8
516
+ # standalone_content_class = mx-auto w-full max-w-4xl rounded-2xl border bg-card
517
+ ```
518
+
519
+ - `test_sidebar`: keeps the developer sidebar (perfect for the demo workspace or Storybook screenshots).
520
+ - `standalone`: renders the page body directly so it inherits your own app shell, layout, and theme tokens.
521
+ - The wrapper and content class overrides let you align spacing/borders with your design system without editing package code.
522
+
523
+ ---
311
524
 
312
525
  ## Authentication Service
313
526
 
@@ -347,6 +560,7 @@ type HazoAuthResult =
347
560
  email_address: string;
348
561
  is_active: boolean;
349
562
  profile_picture_url: string | null;
563
+ url_on_logon: string | null;
350
564
  };
351
565
  permissions: string[];
352
566
  permission_ok: boolean;
@@ -391,6 +605,9 @@ export async function GET(request: NextRequest) {
391
605
  }
392
606
 
393
607
  // User is authenticated and has required permissions
608
+ // Access url_on_logon for custom redirect
609
+ const redirectUrl = authResult.user.url_on_logon || "/dashboard";
610
+
394
611
  return NextResponse.json({
395
612
  message: "Access granted",
396
613
  user: authResult.user,
@@ -412,44 +629,14 @@ export async function GET(request: NextRequest) {
412
629
  }
413
630
  ```
414
631
 
415
- **Non-strict mode (returns permission status without throwing):**
416
-
417
- ```typescript
418
- // Check permissions without throwing errors
419
- const authResult = await hazo_get_auth(request, {
420
- required_permissions: ["admin_user_management"],
421
- strict: false, // Returns permission_ok: false if missing
422
- });
423
-
424
- if (authResult.authenticated && authResult.permission_ok) {
425
- // User has required permissions
426
- } else if (authResult.authenticated) {
427
- // User is authenticated but missing permissions
428
- console.log("Missing permissions:", authResult.missing_permissions);
429
- } else {
430
- // User is not authenticated
431
- }
432
- ```
433
-
434
632
  #### `get_authenticated_user`
435
633
 
436
634
  Basic authentication check for API routes. Returns user info if authenticated, or `{ authenticated: false }` if not.
437
635
 
438
636
  **Location:** `src/lib/auth/auth_utils.server.ts`
439
637
 
440
- **Function Signature:**
441
638
  ```typescript
442
639
  import { get_authenticated_user } from "hazo_auth/lib/auth/auth_utils.server";
443
- import type { AuthResult } from "hazo_auth/lib/auth/auth_utils.server";
444
-
445
- async function get_authenticated_user(request: NextRequest): Promise<AuthResult>
446
- ```
447
-
448
- **Example Usage:**
449
-
450
- ```typescript
451
- import { NextRequest, NextResponse } from "next/server";
452
- import { get_authenticated_user } from "hazo_auth/lib/auth/auth_utils.server";
453
640
 
454
641
  export async function GET(request: NextRequest) {
455
642
  const authResult = await get_authenticated_user(request);
@@ -469,89 +656,12 @@ export async function GET(request: NextRequest) {
469
656
  }
470
657
  ```
471
658
 
472
- #### `require_auth`
473
-
474
- Requires authentication and throws an error if the user is not authenticated. Useful for protected API routes.
475
-
476
- **Location:** `src/lib/auth/auth_utils.server.ts`
477
-
478
- **Function Signature:**
479
- ```typescript
480
- import { require_auth } from "hazo_auth/lib/auth/auth_utils.server";
481
- import type { AuthUser } from "hazo_auth/lib/auth/auth_utils.server";
482
-
483
- async function require_auth(request: NextRequest): Promise<AuthUser>
484
- ```
485
-
486
- **Example Usage:**
487
-
488
- ```typescript
489
- import { NextRequest, NextResponse } from "next/server";
490
- import { require_auth } from "hazo_auth/lib/auth/auth_utils.server";
491
-
492
- export async function GET(request: NextRequest) {
493
- try {
494
- const user = await require_auth(request);
495
- // User is guaranteed to be authenticated here
496
- return NextResponse.json({ user_id: user.user_id, email: user.email });
497
- } catch (error) {
498
- return NextResponse.json(
499
- { error: "Authentication required" },
500
- { status: 401 }
501
- );
502
- }
503
- }
504
- ```
505
-
506
- #### `is_authenticated`
507
-
508
- Simple boolean check for authentication status.
509
-
510
- **Location:** `src/lib/auth/auth_utils.server.ts`
511
-
512
- **Function Signature:**
513
- ```typescript
514
- import { is_authenticated } from "hazo_auth/lib/auth/auth_utils.server";
515
-
516
- async function is_authenticated(request: NextRequest): Promise<boolean>
517
- ```
518
-
519
- **Example Usage:**
520
-
521
- ```typescript
522
- import { NextRequest, NextResponse } from "next/server";
523
- import { is_authenticated } from "hazo_auth/lib/auth/auth_utils.server";
524
-
525
- export async function GET(request: NextRequest) {
526
- const authenticated = await is_authenticated(request);
527
-
528
- if (!authenticated) {
529
- return NextResponse.json(
530
- { error: "Authentication required" },
531
- { status: 401 }
532
- );
533
- }
534
-
535
- // Continue with authenticated logic
536
- }
537
- ```
538
-
539
659
  #### `get_server_auth_user`
540
660
 
541
661
  Gets authenticated user in server components and pages (uses Next.js `cookies()` function).
542
662
 
543
663
  **Location:** `src/lib/auth/server_auth.ts`
544
664
 
545
- **Function Signature:**
546
- ```typescript
547
- import { get_server_auth_user } from "hazo_auth/lib/auth/server_auth";
548
- import type { ServerAuthResult } from "hazo_auth/lib/auth/server_auth";
549
-
550
- async function get_server_auth_user(): Promise<ServerAuthResult>
551
- ```
552
-
553
- **Example Usage:**
554
-
555
665
  ```typescript
556
666
  // In a server component (src/app/dashboard/page.tsx)
557
667
  import { get_server_auth_user } from "hazo_auth/lib/auth/server_auth";
@@ -578,31 +688,7 @@ export default async function DashboardPage() {
578
688
 
579
689
  React hook for fetching authentication status and permissions on the client side.
580
690
 
581
- **Location:** `src/components/layouts/shared/hooks/use_hazo_auth.ts`
582
-
583
- **Function Signature:**
584
- ```typescript
585
- import { use_hazo_auth } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
586
- import type { UseHazoAuthOptions, UseHazoAuthResult } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
587
-
588
- function use_hazo_auth(options?: UseHazoAuthOptions): UseHazoAuthResult
589
- ```
590
-
591
- **Options:**
592
- - `required_permissions?: string[]` - Array of permission names to check
593
- - `strict?: boolean` - If `true`, throws error when permissions are missing (default: `false`)
594
- - `skip?: boolean` - Skip fetch (for conditional use)
595
-
596
- **Return Type:**
597
- ```typescript
598
- type UseHazoAuthResult = HazoAuthResult & {
599
- loading: boolean;
600
- error: Error | null;
601
- refetch: () => Promise<void>;
602
- };
603
- ```
604
-
605
- **Example Usage:**
691
+ **Location:** `src/hooks/use_hazo_auth.ts`
606
692
 
607
693
  ```typescript
608
694
  "use client";
@@ -616,21 +702,10 @@ export function ProtectedComponent() {
616
702
  strict: false,
617
703
  });
618
704
 
619
- if (loading) {
620
- return <div>Loading...</div>;
621
- }
622
-
623
- if (error) {
624
- return <div>Error: {error.message}</div>;
625
- }
626
-
627
- if (!authenticated) {
628
- return <div>Please log in to access this page.</div>;
629
- }
630
-
631
- if (!permission_ok) {
632
- return <div>You don't have permission to access this page.</div>;
633
- }
705
+ if (loading) return <div>Loading...</div>;
706
+ if (error) return <div>Error: {error.message}</div>;
707
+ if (!authenticated) return <div>Please log in to access this page.</div>;
708
+ if (!permission_ok) return <div>You don't have permission to access this page.</div>;
634
709
 
635
710
  return (
636
711
  <div>
@@ -642,298 +717,48 @@ export function ProtectedComponent() {
642
717
  }
643
718
  ```
644
719
 
645
- **Conditional Permission Checks:**
646
-
647
- ```typescript
648
- "use client";
649
-
650
- import { use_hazo_auth } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
651
-
652
- export function ConditionalComponent() {
653
- // Check multiple permissions
654
- const userManagementAuth = use_hazo_auth({
655
- required_permissions: ["admin_user_management"],
656
- });
657
-
658
- const roleManagementAuth = use_hazo_auth({
659
- required_permissions: ["admin_role_management"],
660
- });
661
-
662
- return (
663
- <div>
664
- {userManagementAuth.permission_ok && (
665
- <button>Manage Users</button>
666
- )}
667
- {roleManagementAuth.permission_ok && (
668
- <button>Manage Roles</button>
669
- )}
670
- </div>
671
- );
672
- }
673
- ```
674
-
675
- #### `trigger_hazo_auth_refresh`
676
-
677
- Triggers a refresh of authentication status across all components using `use_hazo_auth`. Useful after login, logout, or permission changes.
720
+ #### `use_auth_status`
678
721
 
679
- **Location:** `src/components/layouts/shared/hooks/use_hazo_auth.ts`
722
+ Simpler hook for basic authentication status checking.
680
723
 
681
- **Function Signature:**
682
- ```typescript
683
- import { trigger_hazo_auth_refresh } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
684
-
685
- function trigger_hazo_auth_refresh(): void
686
- ```
687
-
688
- **Example Usage:**
724
+ **Location:** `src/hooks/use_auth_status.ts`
689
725
 
690
726
  ```typescript
691
727
  "use client";
692
728
 
693
- import { trigger_hazo_auth_refresh } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
729
+ import { use_auth_status } from "hazo_auth/components/layouts/shared/hooks/use_auth_status";
694
730
 
695
- export function LogoutButton() {
696
- const handleLogout = async () => {
697
- await fetch("/api/hazo_auth/logout", { method: "POST" });
698
- trigger_hazo_auth_refresh(); // Notify all components to refresh auth status
699
- window.location.href = "/hazo_auth/login";
700
- };
731
+ export function UserGreeting() {
732
+ const { authenticated, name, email, loading } = use_auth_status();
701
733
 
702
- return <button onClick={handleLogout}>Logout</button>;
734
+ if (loading) return <div>Loading...</div>;
735
+ if (!authenticated) return <div>Please log in</div>;
736
+
737
+ return <div>Welcome, {name || email}!</div>;
703
738
  }
704
739
  ```
705
740
 
706
741
  ### Configuration
707
742
 
708
- The authentication utility can be configured in `hazo_auth_config.ini` under the `[hazo_auth__auth_utility]` section:
743
+ Configure the authentication utility in `hazo_auth_config.ini`:
709
744
 
710
745
  ```ini
711
746
  [hazo_auth__auth_utility]
712
747
  # Cache settings
713
- # Maximum number of users to cache (LRU eviction, default: 10000)
714
748
  cache_max_users = 10000
715
-
716
- # Cache TTL in minutes (default: 15)
717
749
  cache_ttl_minutes = 15
718
-
719
- # Force cache refresh if older than this many minutes (default: 30)
720
750
  cache_max_age_minutes = 30
721
751
 
722
- # Rate limiting for /api/hazo_auth/get_auth endpoint
723
- # Per-user rate limit (requests per minute, default: 100)
752
+ # Rate limiting
724
753
  rate_limit_per_user = 100
725
-
726
- # Per-IP rate limit for unauthenticated requests (default: 200)
727
754
  rate_limit_per_ip = 200
728
755
 
729
756
  # Permission check behavior
730
- # Log all permission denials for security audit (default: true)
731
757
  log_permission_denials = true
732
-
733
- # User-friendly error messages
734
- # Enable mapping of technical permissions to user-friendly messages (default: true)
735
758
  enable_friendly_error_messages = true
736
-
737
- # Permission message mappings (optional, comma-separated: permission_name:user_message)
738
- # Example: admin_user_management:You don't have access to user management,admin_role_management:You don't have access to role management
739
- permission_error_messages =
740
759
  ```
741
760
 
742
- ### Testing Authentication and RBAC
743
-
744
- #### Testing User Authentication
745
-
746
- To test if a user is authenticated, use the `hazo_get_auth` function or the `use_hazo_auth` hook:
747
-
748
- ```typescript
749
- // Server-side test
750
- const authResult = await hazo_get_auth(request);
751
- if (authResult.authenticated) {
752
- console.log("User is authenticated:", authResult.user.email_address);
753
- console.log("User permissions:", authResult.permissions);
754
- } else {
755
- console.log("User is not authenticated");
756
- }
757
-
758
- // Client-side test
759
- const { authenticated, user, permissions } = use_hazo_auth();
760
- if (authenticated) {
761
- console.log("User is authenticated:", user?.email_address);
762
- console.log("User permissions:", permissions);
763
- }
764
- ```
765
-
766
- #### Testing RBAC Permissions
767
-
768
- To test if a user has specific permissions:
769
-
770
- ```typescript
771
- // Server-side - strict mode (throws error if missing)
772
- try {
773
- const authResult = await hazo_get_auth(request, {
774
- required_permissions: ["admin_user_management", "admin_role_management"],
775
- strict: true,
776
- });
777
- // User has all required permissions
778
- console.log("Access granted");
779
- } catch (error) {
780
- if (error instanceof PermissionError) {
781
- console.log("Missing permissions:", error.missing_permissions);
782
- console.log("User permissions:", error.user_permissions);
783
- console.log("User-friendly message:", error.user_friendly_message);
784
- }
785
- }
786
-
787
- // Server-side - non-strict mode (returns status)
788
- const authResult = await hazo_get_auth(request, {
789
- required_permissions: ["admin_user_management"],
790
- strict: false,
791
- });
792
-
793
- if (authResult.authenticated && authResult.permission_ok) {
794
- console.log("User has required permissions");
795
- } else if (authResult.authenticated) {
796
- console.log("User is missing permissions:", authResult.missing_permissions);
797
- }
798
-
799
- // Client-side test
800
- const { permission_ok, missing_permissions, permissions } = use_hazo_auth({
801
- required_permissions: ["admin_user_management"],
802
- });
803
-
804
- if (permission_ok) {
805
- console.log("User has required permissions");
806
- } else {
807
- console.log("Missing permissions:", missing_permissions);
808
- console.log("User permissions:", permissions);
809
- }
810
- ```
811
-
812
- #### Getting All User Permissions
813
-
814
- To get all permissions for the current user:
815
-
816
- ```typescript
817
- // Server-side
818
- const authResult = await hazo_get_auth(request);
819
- if (authResult.authenticated) {
820
- console.log("All user permissions:", authResult.permissions);
821
- // Check if user has a specific permission
822
- const hasPermission = authResult.permissions.includes("admin_user_management");
823
- }
824
-
825
- // Client-side
826
- const { permissions } = use_hazo_auth();
827
- console.log("All user permissions:", permissions);
828
- const hasPermission = permissions.includes("admin_user_management");
829
- ```
830
-
831
- #### Testing in API Routes
832
-
833
- Example of a protected API route with permission checking:
834
-
835
- ```typescript
836
- // src/app/api/admin/users/route.ts
837
- import { NextRequest, NextResponse } from "next/server";
838
- import { hazo_get_auth } from "hazo_auth/lib/auth/hazo_get_auth.server";
839
- import { PermissionError } from "hazo_auth/lib/auth/auth_types";
840
-
841
- export async function GET(request: NextRequest) {
842
- try {
843
- // Require authentication and specific permission
844
- const authResult = await hazo_get_auth(request, {
845
- required_permissions: ["admin_user_management"],
846
- strict: true,
847
- });
848
-
849
- // Fetch users (only accessible to admins)
850
- const users = await fetchUsers();
851
-
852
- return NextResponse.json({ users });
853
- } catch (error) {
854
- if (error instanceof PermissionError) {
855
- return NextResponse.json(
856
- {
857
- error: "Permission denied",
858
- missing_permissions: error.missing_permissions,
859
- user_friendly_message: error.user_friendly_message,
860
- },
861
- { status: 403 }
862
- );
863
- }
864
-
865
- return NextResponse.json(
866
- { error: "Authentication required" },
867
- { status: 401 }
868
- );
869
- }
870
- }
871
- ```
872
-
873
- #### Testing in React Components
874
-
875
- Example of a protected component with permission-based UI:
876
-
877
- ```typescript
878
- "use client";
879
-
880
- import { use_hazo_auth } from "hazo_auth/components/layouts/shared/hooks/use_hazo_auth";
881
-
882
- export function AdminDashboard() {
883
- const userManagementAuth = use_hazo_auth({
884
- required_permissions: ["admin_user_management"],
885
- });
886
-
887
- const roleManagementAuth = use_hazo_auth({
888
- required_permissions: ["admin_role_management"],
889
- });
890
-
891
- if (userManagementAuth.loading || roleManagementAuth.loading) {
892
- return <div>Loading...</div>;
893
- }
894
-
895
- if (!userManagementAuth.authenticated) {
896
- return <div>Please log in to access this page.</div>;
897
- }
898
-
899
- return (
900
- <div>
901
- <h1>Admin Dashboard</h1>
902
- {userManagementAuth.permission_ok && (
903
- <section>
904
- <h2>User Management</h2>
905
- {/* User management UI */}
906
- </section>
907
- )}
908
- {roleManagementAuth.permission_ok && (
909
- <section>
910
- <h2>Role Management</h2>
911
- {/* Role management UI */}
912
- </section>
913
- )}
914
- {!userManagementAuth.permission_ok && !roleManagementAuth.permission_ok && (
915
- <div>You don't have permission to access any admin features.</div>
916
- )}
917
- </div>
918
- );
919
- }
920
- ```
921
-
922
- ### Cache Invalidation
923
-
924
- The authentication cache is automatically invalidated in the following scenarios:
925
- - User logout
926
- - Password change
927
- - User deactivation
928
- - Role assignment changes
929
- - Permission changes to roles
930
-
931
- You can also manually invalidate the cache using the API endpoint:
932
-
933
- ```typescript
934
- // POST /api/hazo_auth/invalidate_cache
935
- // Body: { user_id?: string, role_ids?: number[], invalidate_all?: boolean }
936
- ```
761
+ ---
937
762
 
938
763
  ## Profile Picture Menu Widget
939
764
 
@@ -962,357 +787,157 @@ export function Navbar() {
962
787
  }
963
788
  ```
964
789
 
965
- ### Direct Usage (Manual Configuration)
966
-
967
- If you prefer to configure the component directly without using the config file:
968
-
969
- ```typescript
970
- "use client";
971
-
972
- import { ProfilePicMenu } from "hazo_auth/components/layouts/shared/components/profile_pic_menu";
973
-
974
- export function Navbar() {
975
- return (
976
- <nav className="flex items-center justify-between p-4">
977
- <div>Logo</div>
978
- <ProfilePicMenu
979
- show_single_button={false}
980
- sign_up_label="Sign Up"
981
- sign_in_label="Sign In"
982
- register_path="/hazo_auth/register"
983
- login_path="/hazo_auth/login"
984
- settings_path="/hazo_auth/my_settings"
985
- logout_path="/api/hazo_auth/logout"
986
- avatar_size="default"
987
- className="ml-auto"
988
- />
989
- </nav>
990
- );
991
- }
992
- ```
993
-
994
790
  ### Configuration
995
791
 
996
- Configure the Profile Picture Menu in `hazo_auth_config.ini` under the `[hazo_auth__profile_pic_menu]` section:
997
-
998
792
  ```ini
999
793
  [hazo_auth__profile_pic_menu]
1000
- # Button configuration for unauthenticated users
1001
- # Show only "Sign Up" button when true, show both "Sign Up" and "Sign In" buttons when false (default)
1002
794
  show_single_button = false
1003
-
1004
- # Sign up button label
1005
795
  sign_up_label = Sign Up
1006
-
1007
- # Sign in button label
1008
796
  sign_in_label = Sign In
1009
-
1010
- # Register page path
1011
797
  register_path = /hazo_auth/register
1012
-
1013
- # Login page path
1014
798
  login_path = /hazo_auth/login
1015
-
1016
- # Settings page path (shown in dropdown menu when authenticated)
1017
799
  settings_path = /hazo_auth/my_settings
1018
-
1019
- # Logout API endpoint path
1020
800
  logout_path = /api/hazo_auth/logout
1021
-
1022
801
  # Custom menu items (optional)
1023
- # Format: "type:label:value_or_href:order" for info/link, or "separator:order" for separator
1024
- # Examples:
1025
- # - Info item: "info:Phone:+1234567890:3"
1026
- # - Link item: "link:My Account:/account:4"
1027
- # - Separator: "separator:2"
1028
- # Custom items are added to the default menu items (name, email, separator, Settings, Logout)
1029
- # Items are sorted by type (info first, then separators, then links) and then by order within each type
1030
- custom_menu_items =
802
+ custom_menu_items = info:Phone:+1234567890:3,separator:2,link:My Account:/account:4
1031
803
  ```
1032
804
 
1033
- ### Component Props
1034
-
1035
- #### `ProfilePicMenuWrapper` Props
1036
-
1037
- - `className?: string` - Additional CSS classes
1038
- - `avatar_size?: "sm" | "default" | "lg"` - Size of the profile picture avatar (default: "default")
1039
-
1040
- #### `ProfilePicMenu` Props
805
+ ---
1041
806
 
1042
- - `show_single_button?: boolean` - Show only "Sign Up" button when true (default: false)
1043
- - `sign_up_label?: string` - Label for sign up button (default: "Sign Up")
1044
- - `sign_in_label?: string` - Label for sign in button (default: "Sign In")
1045
- - `register_path?: string` - Path to registration page (default: "/hazo_auth/register")
1046
- - `login_path?: string` - Path to login page (default: "/hazo_auth/login")
1047
- - `settings_path?: string` - Path to settings page (default: "/hazo_auth/my_settings")
1048
- - `logout_path?: string` - Path to logout API endpoint (default: "/api/hazo_auth/logout")
1049
- - `custom_menu_items?: ProfilePicMenuMenuItem[]` - Array of custom menu items
1050
- - `className?: string` - Additional CSS classes
1051
- - `avatar_size?: "sm" | "default" | "lg"` - Size of the profile picture avatar (default: "default")
807
+ ## User Profile Service
1052
808
 
1053
- ### Custom Menu Items
809
+ The `hazo_auth` package provides a batch user profile retrieval service for applications that need basic user information, such as chat applications or user lists.
1054
810
 
1055
- You can add custom menu items to the dropdown menu. Items are automatically sorted by type (info → separator → link) and then by order.
811
+ ### `hazo_get_user_profiles`
1056
812
 
1057
- **Menu Item Types:**
813
+ Retrieves basic profile information for multiple users in a single batch call.
1058
814
 
1059
- 1. **Info** - Display-only text (e.g., phone number, department)
1060
- - Format: `"info:label:value:order"`
1061
- - Example: `"info:Phone:+1234567890:3"`
815
+ **Location:** `src/lib/services/user_profiles_service.ts`
1062
816
 
1063
- 2. **Link** - Clickable menu item that navigates to a URL
1064
- - Format: `"link:label:href:order"`
1065
- - Example: `"link:My Account:/account:4"`
817
+ ```typescript
818
+ import { hazo_get_user_profiles } from "hazo_auth/lib/services/user_profiles_service";
819
+ import { get_hazo_connect_instance } from "hazo_auth/server/hazo_connect_instance.server";
1066
820
 
1067
- 3. **Separator** - Visual separator line
1068
- - Format: `"separator:order"`
1069
- - Example: `"separator:2"`
821
+ export async function GET(request: NextRequest) {
822
+ const adapter = get_hazo_connect_instance();
823
+
824
+ const result = await hazo_get_user_profiles(adapter, [
825
+ "user-id-1",
826
+ "user-id-2",
827
+ "user-id-3",
828
+ ]);
1070
829
 
1071
- **Example Configuration:**
830
+ if (!result.success) {
831
+ return NextResponse.json({ error: result.error }, { status: 500 });
832
+ }
1072
833
 
1073
- ```ini
1074
- [hazo_auth__profile_pic_menu]
1075
- # Add custom menu items
1076
- custom_menu_items = info:Phone:+1234567890:3,separator:2,link:My Account:/account:4,link:Help:/help:5
834
+ return NextResponse.json({
835
+ profiles: result.profiles,
836
+ not_found: result.not_found_ids,
837
+ });
838
+ }
1077
839
  ```
1078
840
 
1079
- This will create a menu with:
1080
- 1. Default items (name, email, separator, Settings, Logout)
1081
- 2. Custom info item: "Phone: +1234567890" (order 3)
1082
- 3. Custom separator (order 2)
1083
- 4. Custom link: "My Account" → `/account` (order 4)
1084
- 5. Custom link: "Help" → `/help` (order 5)
841
+ ---
1085
842
 
1086
- Items are sorted by type priority (info < separator < link) and then by order within each type.
843
+ ## Local Development (for package contributors)
1087
844
 
1088
- ### Default Menu Items
845
+ ### Prerequisites
1089
846
 
1090
- When authenticated, the dropdown menu automatically includes:
1091
- - User's name (if available)
1092
- - User's email address
1093
- - Separator
1094
- - Settings link (with Settings icon)
1095
- - Logout link (with LogOut icon, triggers logout action)
847
+ - Node.js 18+
848
+ - npm 9+
1096
849
 
1097
- ### Examples
850
+ ### Setup
1098
851
 
1099
- #### Example 1: Simple Navbar Integration
852
+ ```bash
853
+ # Clone the repository
854
+ git clone <repository-url>
855
+ cd hazo_auth
1100
856
 
1101
- ```typescript
1102
- // app/components/navbar.tsx
1103
- import { ProfilePicMenuWrapper } from "hazo_auth/components/layouts/shared/components/profile_pic_menu_wrapper";
857
+ # Install dependencies
858
+ npm install
1104
859
 
1105
- export function Navbar() {
1106
- return (
1107
- <header className="border-b">
1108
- <nav className="container mx-auto flex items-center justify-between p-4">
1109
- <div className="text-xl font-bold">My App</div>
1110
- <ProfilePicMenuWrapper />
1111
- </nav>
1112
- </header>
1113
- );
1114
- }
860
+ # Copy configuration files
861
+ cp hazo_auth_config.example.ini hazo_auth_config.ini
862
+ cp hazo_notify_config.example.ini hazo_notify_config.ini
1115
863
  ```
1116
864
 
1117
- #### Example 2: Custom Styling and Size
1118
-
1119
- ```typescript
1120
- // app/components/navbar.tsx
1121
- import { ProfilePicMenuWrapper } from "hazo_auth/components/layouts/shared/components/profile_pic_menu_wrapper";
865
+ ### Development Commands
1122
866
 
1123
- export function Navbar() {
1124
- return (
1125
- <header className="bg-slate-900 text-white">
1126
- <nav className="container mx-auto flex items-center justify-between p-4">
1127
- <div className="text-xl font-bold">My App</div>
1128
- <ProfilePicMenuWrapper
1129
- avatar_size="sm"
1130
- className="bg-slate-800 rounded-lg p-2"
1131
- />
1132
- </nav>
1133
- </header>
1134
- );
1135
- }
1136
- ```
867
+ ```bash
868
+ # Start development server
869
+ npm run dev
1137
870
 
1138
- #### Example 3: With Custom Menu Items (Programmatic)
871
+ # Run Storybook
872
+ npm run storybook
1139
873
 
1140
- ```typescript
1141
- "use client";
874
+ # Build the package for distribution
875
+ npm run build:pkg
1142
876
 
1143
- import { ProfilePicMenu } from "hazo_auth/components/layouts/shared/components/profile_pic_menu";
1144
- import type { ProfilePicMenuMenuItem } from "hazo_auth/lib/profile_pic_menu_config.server";
877
+ # Run tests
878
+ npm test
1145
879
 
1146
- export function Navbar() {
1147
- const customItems: ProfilePicMenuMenuItem[] = [
1148
- {
1149
- type: "info",
1150
- label: "Department",
1151
- value: "Engineering",
1152
- order: 3,
1153
- id: "dept_info",
1154
- },
1155
- {
1156
- type: "separator",
1157
- order: 2,
1158
- id: "custom_sep",
1159
- },
1160
- {
1161
- type: "link",
1162
- label: "Documentation",
1163
- href: "/docs",
1164
- order: 4,
1165
- id: "docs_link",
1166
- },
1167
- ];
880
+ # Initialize database users/roles
881
+ npm run init-users
1168
882
 
1169
- return (
1170
- <nav className="flex items-center justify-between p-4">
1171
- <div>Logo</div>
1172
- <ProfilePicMenu
1173
- custom_menu_items={customItems}
1174
- avatar_size="default"
1175
- />
1176
- </nav>
1177
- );
1178
- }
883
+ # Apply database migrations
884
+ npx tsx scripts/apply_migration.ts [migration_file_path]
1179
885
  ```
1180
886
 
1181
- #### Example 4: Single Button Mode
887
+ ### Project Structure
1182
888
 
1183
- ```typescript
1184
- // In hazo_auth_config.ini
1185
- [hazo_auth__profile_pic_menu]
1186
- show_single_button = true
1187
- sign_up_label = Get Started
1188
889
  ```
1189
-
1190
- When `show_single_button` is `true`, only the "Sign Up" button is shown for unauthenticated users (no "Sign In" button).
1191
-
1192
- ### Behavior
1193
-
1194
- - **Loading State**: Shows a pulsing placeholder while checking authentication status
1195
- - **Unauthenticated**: Shows Sign Up/Sign In buttons (or single button if configured)
1196
- - **Authenticated**: Shows profile picture with dropdown menu
1197
- - **Profile Picture Fallback**: If no profile picture is set, shows user's initials
1198
- - **Logout**: Handles logout action, refreshes auth status, and redirects appropriately
1199
- - **Responsive**: Works well in both navbar and sidebar layouts
1200
-
1201
- ### Styling
1202
-
1203
- The component uses TailwindCSS classes and can be customized with:
1204
- - `className` prop for additional styling
1205
- - `avatar_size` prop for different avatar sizes
1206
- - CSS class names prefixed with `cls_profile_pic_menu_*` for targeted styling
1207
-
1208
- Example custom styling:
1209
-
1210
- ```css
1211
- /* Target specific elements */
1212
- .cls_profile_pic_menu_avatar {
1213
- border: 2px solid #3b82f6;
1214
- }
1215
-
1216
- .cls_profile_pic_menu_dropdown {
1217
- min-width: 200px;
1218
- }
890
+ hazo_auth/
891
+ ├── src/
892
+ │ ├── app/ # Next.js app directory (demo pages)
893
+ │ ├── components/ # React components
894
+ │ │ ├── layouts/ # Layout components (login, register, etc.)
895
+ │ │ └── ui/ # Reusable UI components (shadcn-based)
896
+ │ ├── hooks/ # Client-side React hooks
897
+ │ ├── lib/ # Shared utilities and services
898
+ │ │ ├── auth/ # Authentication utilities
899
+ │ │ ├── config/ # Configuration loaders
900
+ │ │ └── services/ # Business logic services
901
+ │ ├── server/ # Server-only utilities
902
+ │ └── index.ts # Main entry point
903
+ ├── dist/ # Compiled package output
904
+ ├── migrations/ # Database migration files
905
+ ├── scripts/ # Utility scripts
906
+ ├── __tests__/ # Test files and fixtures
907
+ └── public/ # Static assets
1219
908
  ```
1220
909
 
1221
- ## User Profile Service
1222
-
1223
- The `hazo_auth` package provides a batch user profile retrieval service for applications that need basic user information, such as chat applications or user lists.
1224
-
1225
- ### `hazo_get_user_profiles`
1226
-
1227
- Retrieves basic profile information for multiple users in a single batch call.
1228
-
1229
- **Location:** `src/lib/services/user_profiles_service.ts`
1230
-
1231
- **Function Signature:**
1232
- ```typescript
1233
- import { hazo_get_user_profiles } from "hazo_auth/lib/services/user_profiles_service";
1234
- import type { GetProfilesResult, UserProfileInfo } from "hazo_auth/lib/services/user_profiles_service";
910
+ ### Building the Package
1235
911
 
1236
- async function hazo_get_user_profiles(
1237
- adapter: HazoConnectAdapter,
1238
- user_ids: string[],
1239
- ): Promise<GetProfilesResult>
1240
- ```
912
+ The package is built using TypeScript with a separate build configuration:
1241
913
 
1242
- **Return Type:**
1243
- ```typescript
1244
- type UserProfileInfo = {
1245
- user_id: string;
1246
- profile_picture_url: string | null;
1247
- email: string;
1248
- name: string | null;
1249
- days_since_created: number;
1250
- };
1251
-
1252
- type GetProfilesResult = {
1253
- success: boolean;
1254
- profiles: UserProfileInfo[];
1255
- not_found_ids: string[];
1256
- error?: string;
1257
- };
914
+ ```bash
915
+ npm run build:pkg
1258
916
  ```
1259
917
 
1260
- **Features:**
1261
- - **Batch Retrieval:** Fetches multiple user profiles in a single database query
1262
- - **Deduplication:** Automatically removes duplicate user IDs from input
1263
- - **Not Found Tracking:** Returns list of user IDs that were not found in the database
1264
- - **Profile Picture:** Returns the resolved profile picture URL (Gravatar, library, or uploaded)
1265
- - **Account Age:** Calculates days since account creation
918
+ This compiles the `src/` directory to `dist/` with:
919
+ - Type declarations (`.d.ts` files)
920
+ - ES modules output
921
+ - Excludes Next.js app directory and Storybook stories
1266
922
 
1267
- **Example Usage:**
923
+ ### Package Exports
1268
924
 
1269
- ```typescript
1270
- // In an API route or server component
1271
- import { hazo_get_user_profiles } from "hazo_auth/lib/services/user_profiles_service";
1272
- import { get_hazo_connect_instance } from "hazo_auth/lib/hazo_connect_instance.server";
1273
-
1274
- export async function GET(request: NextRequest) {
1275
- const adapter = get_hazo_connect_instance();
1276
-
1277
- // Get profiles for multiple users (e.g., chat participants)
1278
- const result = await hazo_get_user_profiles(adapter, [
1279
- "user-id-1",
1280
- "user-id-2",
1281
- "user-id-3",
1282
- ]);
925
+ The `package.json` exports field defines the public API:
1283
926
 
1284
- if (!result.success) {
1285
- return NextResponse.json({ error: result.error }, { status: 500 });
927
+ ```json
928
+ {
929
+ "exports": {
930
+ ".": "./dist/index.js",
931
+ "./components/*": "./dist/components/*.js",
932
+ "./components/ui/*": "./dist/components/ui/*.js",
933
+ "./components/layouts/*": "./dist/components/layouts/*.js",
934
+ "./lib/*": "./dist/lib/*.js",
935
+ "./hooks/*": "./dist/hooks/*.js",
936
+ "./server/*": "./dist/server/*.js"
1286
937
  }
1287
-
1288
- // result.profiles contains found user profiles
1289
- // result.not_found_ids contains IDs that weren't found
1290
- return NextResponse.json({
1291
- profiles: result.profiles,
1292
- not_found: result.not_found_ids,
1293
- });
1294
938
  }
1295
939
  ```
1296
940
 
1297
- **Use Cases:**
1298
- - Chat applications displaying participant information
1299
- - User lists with profile pictures and names
1300
- - Activity feeds showing user details
1301
- - Any feature requiring batch user profile lookups
1302
-
1303
- ### Local Development (for package contributors)
1304
-
1305
- - `npm install` to install dependencies.
1306
- - `npm run dev` launches the Next.js app at `http://localhost:3000`.
1307
- - `npm run storybook` launches Storybook at `http://localhost:6006`.
1308
-
1309
- ### Project Structure
1310
-
1311
- - `src/app` contains the application shell and route composition.
1312
- - `src/lib` is the home for shared utilities and authentication functions.
1313
- - `src/components` contains React components and hooks.
1314
- - `src/stories` holds Storybook stories for documenting components.
1315
-
1316
941
  ### Next Steps
1317
942
 
1318
943
  - Use `npx shadcn@latest add <component>` to scaffold new UI primitives.