@stone-js/starters 0.8.3

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 (352) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +101 -0
  3. package/basic-react-declarative/LICENSE +21 -0
  4. package/basic-react-declarative/README.md +39 -0
  5. package/basic-react-declarative/app/Application.tsx +89 -0
  6. package/basic-react-declarative/assets/css/index.css +26 -0
  7. package/basic-react-declarative/package.json +39 -0
  8. package/basic-react-declarative/public/logo.png +0 -0
  9. package/basic-react-declarative/tests/Application.spec.ts +96 -0
  10. package/basic-react-declarative/tests/__snapshots__/Application.spec.ts.snap +3 -0
  11. package/basic-react-declarative/tsconfig.json +33 -0
  12. package/basic-react-declarative/vitest.config.ts +24 -0
  13. package/basic-react-imperative/LICENSE +21 -0
  14. package/basic-react-imperative/README.md +39 -0
  15. package/basic-react-imperative/app/Application.tsx +89 -0
  16. package/basic-react-imperative/assets/css/index.css +26 -0
  17. package/basic-react-imperative/package.json +39 -0
  18. package/basic-react-imperative/public/logo.png +0 -0
  19. package/basic-react-imperative/tests/Application.spec.ts +80 -0
  20. package/basic-react-imperative/tests/__snapshots__/Application.spec.ts.snap +3 -0
  21. package/basic-react-imperative/tsconfig.json +33 -0
  22. package/basic-react-imperative/vitest.config.ts +24 -0
  23. package/basic-service-declarative/LICENSE +21 -0
  24. package/basic-service-declarative/README.md +39 -0
  25. package/basic-service-declarative/app/Application.ts +56 -0
  26. package/basic-service-declarative/package.json +34 -0
  27. package/basic-service-declarative/tests/Application.spec.ts +60 -0
  28. package/basic-service-declarative/tsconfig.json +25 -0
  29. package/basic-service-declarative/vitest.config.ts +24 -0
  30. package/basic-service-imperative/LICENSE +21 -0
  31. package/basic-service-imperative/README.md +39 -0
  32. package/basic-service-imperative/app/Application.ts +60 -0
  33. package/basic-service-imperative/package.json +34 -0
  34. package/basic-service-imperative/tests/Application.spec.ts +52 -0
  35. package/basic-service-imperative/tsconfig.json +25 -0
  36. package/basic-service-imperative/vitest.config.ts +24 -0
  37. package/continuum-showcase/README.md +44 -0
  38. package/continuum-showcase/app/env.d.ts +34 -0
  39. package/continuum-showcase/app/layouts/MainLayout.tsx +20 -0
  40. package/continuum-showcase/app/pages/BlogPostPage.tsx +62 -0
  41. package/continuum-showcase/app/pages/HomePage.tsx +58 -0
  42. package/continuum-showcase/package.json +25 -0
  43. package/continuum-showcase/stone.config.mjs +20 -0
  44. package/full-react-declarative/.env.example +1 -0
  45. package/full-react-declarative/.env.public.example +1 -0
  46. package/full-react-declarative/LICENSE +21 -0
  47. package/full-react-declarative/README.md +39 -0
  48. package/full-react-declarative/app/Application.ts +85 -0
  49. package/full-react-declarative/app/clients/AxiosClient.ts +136 -0
  50. package/full-react-declarative/app/clients/CommentClient.ts +61 -0
  51. package/full-react-declarative/app/clients/PostClient.ts +90 -0
  52. package/full-react-declarative/app/clients/SecurityClient.ts +66 -0
  53. package/full-react-declarative/app/clients/UserClient.ts +97 -0
  54. package/full-react-declarative/app/components/ChangePasswordForm/ChangePasswordForm.tsx +50 -0
  55. package/full-react-declarative/app/components/CommentForm/CommentForm.tsx +37 -0
  56. package/full-react-declarative/app/components/CommentItem/CommentItem.tsx +42 -0
  57. package/full-react-declarative/app/components/CommentWidget/CommentWidget.tsx +95 -0
  58. package/full-react-declarative/app/components/LoginForm/LoginForm.css +0 -0
  59. package/full-react-declarative/app/components/LoginForm/LoginForm.tsx +71 -0
  60. package/full-react-declarative/app/components/PostDetails/PostDetails.tsx +44 -0
  61. package/full-react-declarative/app/components/PostForm/PostForm.css +0 -0
  62. package/full-react-declarative/app/components/PostForm/PostForm.tsx +47 -0
  63. package/full-react-declarative/app/components/PostItem/PostItem.css +0 -0
  64. package/full-react-declarative/app/components/PostItem/PostItem.tsx +34 -0
  65. package/full-react-declarative/app/components/RegisterForm/RegisterForm.tsx +110 -0
  66. package/full-react-declarative/app/components/UserForm/UserForm.tsx +47 -0
  67. package/full-react-declarative/app/configurations/AppConfiguration.ts +17 -0
  68. package/full-react-declarative/app/error-pages/DefaultErrorPage/DefaultErrorPage.css +0 -0
  69. package/full-react-declarative/app/error-pages/DefaultErrorPage/DefaultErrorPage.tsx +52 -0
  70. package/full-react-declarative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.css +0 -0
  71. package/full-react-declarative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.tsx +53 -0
  72. package/full-react-declarative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.css +0 -0
  73. package/full-react-declarative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.tsx +54 -0
  74. package/full-react-declarative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.css +0 -0
  75. package/full-react-declarative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.tsx +53 -0
  76. package/full-react-declarative/app/errors/ForbiddenError.ts +11 -0
  77. package/full-react-declarative/app/errors/PostNotFoundError.ts +11 -0
  78. package/full-react-declarative/app/errors/UnauthorizedError.ts +11 -0
  79. package/full-react-declarative/app/errors/UserNotFoundError.ts +11 -0
  80. package/full-react-declarative/app/events/UserEvent.ts +18 -0
  81. package/full-react-declarative/app/layout/AppLayout/AppLayout.css +20 -0
  82. package/full-react-declarative/app/layout/AppLayout/AppLayout.tsx +101 -0
  83. package/full-react-declarative/app/layout/ErrorLayout/ErrorLayout.css +0 -0
  84. package/full-react-declarative/app/layout/ErrorLayout/ErrorLayout.tsx +41 -0
  85. package/full-react-declarative/app/layout/SecurityLayout/SecurityLayout.css +0 -0
  86. package/full-react-declarative/app/layout/SecurityLayout/SecurityLayout.tsx +39 -0
  87. package/full-react-declarative/app/middleware/AuthMiddleware.ts +85 -0
  88. package/full-react-declarative/app/models/Comment.ts +31 -0
  89. package/full-react-declarative/app/models/Post.ts +22 -0
  90. package/full-react-declarative/app/models/User.ts +62 -0
  91. package/full-react-declarative/app/pages/home/HomePage.tsx +44 -0
  92. package/full-react-declarative/app/pages/login/LoginPage.css +0 -0
  93. package/full-react-declarative/app/pages/login/LoginPage.tsx +73 -0
  94. package/full-react-declarative/app/pages/posts/CreatePostPage/CreatePostPage.css +0 -0
  95. package/full-react-declarative/app/pages/posts/CreatePostPage/CreatePostPage.tsx +67 -0
  96. package/full-react-declarative/app/pages/posts/PostPage/PostPage.tsx +60 -0
  97. package/full-react-declarative/app/pages/posts/ShowPostPage/ShowPostPage.tsx +83 -0
  98. package/full-react-declarative/app/pages/posts/UpdatePostPage/UpdatePostPage.tsx +77 -0
  99. package/full-react-declarative/app/pages/register/RegisterPage.tsx +68 -0
  100. package/full-react-declarative/app/pages/users/CreateUserPage.tsx +48 -0
  101. package/full-react-declarative/app/pages/users/ShowUserPage.tsx +62 -0
  102. package/full-react-declarative/app/pages/users/UpdateUserPage.tsx +57 -0
  103. package/full-react-declarative/app/pages/users/UserPage.tsx +57 -0
  104. package/full-react-declarative/app/providers/AppServiceProvider.ts +43 -0
  105. package/full-react-declarative/app/services/CommentService.ts +59 -0
  106. package/full-react-declarative/app/services/PostService.ts +108 -0
  107. package/full-react-declarative/app/services/SecurityService.ts +80 -0
  108. package/full-react-declarative/app/services/TokenService.ts +116 -0
  109. package/full-react-declarative/app/services/UserService.ts +126 -0
  110. package/full-react-declarative/app/utils.ts +17 -0
  111. package/full-react-declarative/assets/css/index.css +301 -0
  112. package/full-react-declarative/assets/img/logo.png +0 -0
  113. package/full-react-declarative/package.json +46 -0
  114. package/full-react-declarative/public/logo.png +0 -0
  115. package/full-react-declarative/public/vite.svg +1 -0
  116. package/full-react-declarative/stone.config.mjs +12 -0
  117. package/full-react-declarative/tsconfig.json +29 -0
  118. package/full-react-declarative/vitest.config.ts +24 -0
  119. package/full-react-imperative/.env.example +1 -0
  120. package/full-react-imperative/.env.public.example +1 -0
  121. package/full-react-imperative/LICENSE +21 -0
  122. package/full-react-imperative/README.md +39 -0
  123. package/full-react-imperative/app/Application.ts +79 -0
  124. package/full-react-imperative/app/clients/AxiosClient.ts +124 -0
  125. package/full-react-imperative/app/clients/CommentClient.ts +57 -0
  126. package/full-react-imperative/app/clients/PostClient.ts +86 -0
  127. package/full-react-imperative/app/clients/SecurityClient.ts +60 -0
  128. package/full-react-imperative/app/clients/UserClient.ts +93 -0
  129. package/full-react-imperative/app/clients/contracts/IAxiosClient.ts +97 -0
  130. package/full-react-imperative/app/clients/contracts/ICommentClient.ts +31 -0
  131. package/full-react-imperative/app/clients/contracts/IPostClient.ts +55 -0
  132. package/full-react-imperative/app/clients/contracts/ISecurityClient.ts +33 -0
  133. package/full-react-imperative/app/clients/contracts/IUserClient.ts +61 -0
  134. package/full-react-imperative/app/components/ChangePasswordForm/ChangePasswordForm.tsx +50 -0
  135. package/full-react-imperative/app/components/CommentForm/CommentForm.css +35 -0
  136. package/full-react-imperative/app/components/CommentForm/CommentForm.tsx +45 -0
  137. package/full-react-imperative/app/components/CommentItem/CommentItem.css +74 -0
  138. package/full-react-imperative/app/components/CommentItem/CommentItem.tsx +62 -0
  139. package/full-react-imperative/app/components/CommentWidget/CommentWidget.css +25 -0
  140. package/full-react-imperative/app/components/CommentWidget/CommentWidget.tsx +119 -0
  141. package/full-react-imperative/app/components/Dropdown/Dropdown.css +52 -0
  142. package/full-react-imperative/app/components/Dropdown/Dropdown.tsx +40 -0
  143. package/full-react-imperative/app/components/LayoutHeader/LayoutHeader.css +62 -0
  144. package/full-react-imperative/app/components/LayoutHeader/LayoutHeader.tsx +61 -0
  145. package/full-react-imperative/app/components/LayoutLeftMenu/LayoutLeftMenu.css +25 -0
  146. package/full-react-imperative/app/components/LayoutLeftMenu/LayoutLeftMenu.tsx +32 -0
  147. package/full-react-imperative/app/components/LoginForm/LoginForm.css +0 -0
  148. package/full-react-imperative/app/components/LoginForm/LoginForm.tsx +71 -0
  149. package/full-react-imperative/app/components/NotificationBadge/NotificationBadge.css +41 -0
  150. package/full-react-imperative/app/components/NotificationBadge/NotificationBadge.tsx +63 -0
  151. package/full-react-imperative/app/components/PostCard/PostCard.css +129 -0
  152. package/full-react-imperative/app/components/PostCard/PostCard.tsx +65 -0
  153. package/full-react-imperative/app/components/PostForm/PostForm.css +92 -0
  154. package/full-react-imperative/app/components/PostForm/PostForm.tsx +76 -0
  155. package/full-react-imperative/app/components/PostSkeleton/PostSkeleton.css +65 -0
  156. package/full-react-imperative/app/components/PostSkeleton/PostSkeleton.tsx +25 -0
  157. package/full-react-imperative/app/components/PostWidget/PostWidget.tsx +95 -0
  158. package/full-react-imperative/app/components/ProfileForm/ProfileForm.css +84 -0
  159. package/full-react-imperative/app/components/ProfileForm/ProfileForm.tsx +79 -0
  160. package/full-react-imperative/app/components/RegisterForm/RegisterForm.tsx +110 -0
  161. package/full-react-imperative/app/components/RightAsidePanel/RightAsidePanel.css +32 -0
  162. package/full-react-imperative/app/components/RightAsidePanel/RightAsidePanel.tsx +62 -0
  163. package/full-react-imperative/app/components/SettingsForm/SettingsForm.css +126 -0
  164. package/full-react-imperative/app/components/SettingsForm/SettingsForm.tsx +86 -0
  165. package/full-react-imperative/app/components/UserAvatar/UserAvatar.css +18 -0
  166. package/full-react-imperative/app/components/UserAvatar/UserAvatar.tsx +60 -0
  167. package/full-react-imperative/app/components/UserBadge/UserBadge.css +33 -0
  168. package/full-react-imperative/app/components/UserBadge/UserBadge.tsx +49 -0
  169. package/full-react-imperative/app/components/UserCard/UserCard.css +70 -0
  170. package/full-react-imperative/app/components/UserCard/UserCard.tsx +43 -0
  171. package/full-react-imperative/app/configurations/AppConfiguration.ts +19 -0
  172. package/full-react-imperative/app/error-pages/DefaultErrorPage/DefaultErrorPage.css +0 -0
  173. package/full-react-imperative/app/error-pages/DefaultErrorPage/DefaultErrorPage.tsx +41 -0
  174. package/full-react-imperative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.css +0 -0
  175. package/full-react-imperative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.tsx +42 -0
  176. package/full-react-imperative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.css +0 -0
  177. package/full-react-imperative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.tsx +49 -0
  178. package/full-react-imperative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.css +0 -0
  179. package/full-react-imperative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.tsx +42 -0
  180. package/full-react-imperative/app/errors/ForbiddenError.ts +11 -0
  181. package/full-react-imperative/app/errors/PostNotFoundError.ts +11 -0
  182. package/full-react-imperative/app/errors/UnauthorizedError.ts +11 -0
  183. package/full-react-imperative/app/errors/UserNotFoundError.ts +11 -0
  184. package/full-react-imperative/app/events/UserEvent.ts +18 -0
  185. package/full-react-imperative/app/layout/AppLayout/AppLayout.css +106 -0
  186. package/full-react-imperative/app/layout/AppLayout/AppLayout.tsx +48 -0
  187. package/full-react-imperative/app/layout/ErrorLayout/ErrorLayout.css +0 -0
  188. package/full-react-imperative/app/layout/ErrorLayout/ErrorLayout.tsx +45 -0
  189. package/full-react-imperative/app/layout/SecurityLayout/SecurityLayout.css +0 -0
  190. package/full-react-imperative/app/layout/SecurityLayout/SecurityLayout.tsx +43 -0
  191. package/full-react-imperative/app/layout/SettingsLayout/SettingsLayout.css +99 -0
  192. package/full-react-imperative/app/layout/SettingsLayout/SettingsLayout.tsx +44 -0
  193. package/full-react-imperative/app/middleware/AuthMiddleware.ts +56 -0
  194. package/full-react-imperative/app/models/Comment.ts +35 -0
  195. package/full-react-imperative/app/models/Post.ts +27 -0
  196. package/full-react-imperative/app/models/User.ts +68 -0
  197. package/full-react-imperative/app/pages/Settings/SettingsPage.tsx +23 -0
  198. package/full-react-imperative/app/pages/home/HomePage.tsx +58 -0
  199. package/full-react-imperative/app/pages/login/LoginPage.css +0 -0
  200. package/full-react-imperative/app/pages/login/LoginPage.tsx +65 -0
  201. package/full-react-imperative/app/pages/posts/ShowPostPage/ShowPostPage.tsx +64 -0
  202. package/full-react-imperative/app/pages/posts/UpdatePostPage/UpdatePostPage.tsx +56 -0
  203. package/full-react-imperative/app/pages/register/RegisterPage.tsx +71 -0
  204. package/full-react-imperative/app/pages/users/ShowUserPage/ShowUserPage.css +64 -0
  205. package/full-react-imperative/app/pages/users/ShowUserPage/ShowUserPage.tsx +104 -0
  206. package/full-react-imperative/app/pages/users/UpdateUserPage/UpdateUserPage.css +0 -0
  207. package/full-react-imperative/app/pages/users/UpdateUserPage/UpdateUserPage.tsx +43 -0
  208. package/full-react-imperative/app/pages/users/UserPage/UserPage.css +31 -0
  209. package/full-react-imperative/app/pages/users/UserPage/UserPage.tsx +59 -0
  210. package/full-react-imperative/app/pages/utils.ts +67 -0
  211. package/full-react-imperative/app/providers/AppServiceProvider.ts +40 -0
  212. package/full-react-imperative/app/services/CommentService.ts +53 -0
  213. package/full-react-imperative/app/services/PostService.ts +102 -0
  214. package/full-react-imperative/app/services/SecurityService.ts +72 -0
  215. package/full-react-imperative/app/services/TokenService.ts +108 -0
  216. package/full-react-imperative/app/services/UserService.ts +115 -0
  217. package/full-react-imperative/app/services/contracts/ICommentService.ts +30 -0
  218. package/full-react-imperative/app/services/contracts/IPostService.ts +65 -0
  219. package/full-react-imperative/app/services/contracts/ISecurityService.ts +39 -0
  220. package/full-react-imperative/app/services/contracts/ITokenService.ts +44 -0
  221. package/full-react-imperative/app/services/contracts/IUserService.ts +70 -0
  222. package/full-react-imperative/app/utils.ts +31 -0
  223. package/full-react-imperative/assets/css/index.css +301 -0
  224. package/full-react-imperative/assets/img/logo.png +0 -0
  225. package/full-react-imperative/package.json +48 -0
  226. package/full-react-imperative/public/logo.png +0 -0
  227. package/full-react-imperative/public/vite.svg +1 -0
  228. package/full-react-imperative/stone.config.mjs +12 -0
  229. package/full-react-imperative/tsconfig.json +29 -0
  230. package/full-react-imperative/vitest.config.ts +24 -0
  231. package/full-service-declarative/.env.example +2 -0
  232. package/full-service-declarative/LICENSE +21 -0
  233. package/full-service-declarative/README.md +65 -0
  234. package/full-service-declarative/app/Application.ts +327 -0
  235. package/full-service-declarative/app/commands/ListSessionsCommand.ts +70 -0
  236. package/full-service-declarative/app/commands/ListUsersCommand.ts +56 -0
  237. package/full-service-declarative/app/configurations/AppConfiguration.ts +52 -0
  238. package/full-service-declarative/app/configurations/UserLiveConfiguration.ts +28 -0
  239. package/full-service-declarative/app/database/DatabaseClient.ts +43 -0
  240. package/full-service-declarative/app/database/schema.ts +43 -0
  241. package/full-service-declarative/app/error-handlers/SecurityErrorHandler.ts +61 -0
  242. package/full-service-declarative/app/errors/CredentialsError.ts +12 -0
  243. package/full-service-declarative/app/events/UserEvent.ts +17 -0
  244. package/full-service-declarative/app/handlers/CommentEventHandler.ts +103 -0
  245. package/full-service-declarative/app/handlers/PostEventHandler.ts +104 -0
  246. package/full-service-declarative/app/handlers/SecurityEventHandler.ts +108 -0
  247. package/full-service-declarative/app/handlers/UserEventHandler.ts +159 -0
  248. package/full-service-declarative/app/listeners/UserEventListener.ts +35 -0
  249. package/full-service-declarative/app/middleware/AuthMiddleware.ts +54 -0
  250. package/full-service-declarative/app/models/Comment.ts +38 -0
  251. package/full-service-declarative/app/models/Post.ts +50 -0
  252. package/full-service-declarative/app/models/Session.ts +14 -0
  253. package/full-service-declarative/app/models/User.ts +77 -0
  254. package/full-service-declarative/app/providers/DrizzleServiceProvider.ts +59 -0
  255. package/full-service-declarative/app/repositories/CommentRepository.ts +155 -0
  256. package/full-service-declarative/app/repositories/PostRepository.ts +138 -0
  257. package/full-service-declarative/app/repositories/SessionRepository.ts +123 -0
  258. package/full-service-declarative/app/repositories/UserRepository.ts +99 -0
  259. package/full-service-declarative/app/services/CommentService.ts +112 -0
  260. package/full-service-declarative/app/services/PostService.ts +100 -0
  261. package/full-service-declarative/app/services/SecurityService.ts +232 -0
  262. package/full-service-declarative/app/services/SessionService.ts +130 -0
  263. package/full-service-declarative/app/services/UserService.ts +110 -0
  264. package/full-service-declarative/app/subscribers/UserEventSubscriber.ts +38 -0
  265. package/full-service-declarative/drizzle.config.ts +13 -0
  266. package/full-service-declarative/package.json +48 -0
  267. package/full-service-declarative/stone.config.mjs +12 -0
  268. package/full-service-declarative/tsconfig.json +25 -0
  269. package/full-service-declarative/vitest.config.ts +24 -0
  270. package/full-service-imperative/.env.example +2 -0
  271. package/full-service-imperative/LICENSE +21 -0
  272. package/full-service-imperative/README.md +65 -0
  273. package/full-service-imperative/app/Application.ts +317 -0
  274. package/full-service-imperative/app/commands/ListSessionsCommand.ts +54 -0
  275. package/full-service-imperative/app/commands/ListUsersCommand.ts +42 -0
  276. package/full-service-imperative/app/configurations/AppConfiguration.ts +44 -0
  277. package/full-service-imperative/app/configurations/UserLiveConfiguration.ts +26 -0
  278. package/full-service-imperative/app/database/DatabaseClient.ts +39 -0
  279. package/full-service-imperative/app/database/schema.ts +43 -0
  280. package/full-service-imperative/app/error-handlers/SecurityErrorHandler.ts +58 -0
  281. package/full-service-imperative/app/errors/CredentialsError.ts +12 -0
  282. package/full-service-imperative/app/events/UserEvent.ts +17 -0
  283. package/full-service-imperative/app/handlers/CommentEventHandler.ts +99 -0
  284. package/full-service-imperative/app/handlers/PostEventHandler.ts +99 -0
  285. package/full-service-imperative/app/handlers/SecurityEventHandler.ts +83 -0
  286. package/full-service-imperative/app/handlers/UserEventHandler.ts +132 -0
  287. package/full-service-imperative/app/listeners/UserEventListener.ts +23 -0
  288. package/full-service-imperative/app/middleware/AuthMiddleware.ts +44 -0
  289. package/full-service-imperative/app/models/Comment.ts +38 -0
  290. package/full-service-imperative/app/models/Post.ts +50 -0
  291. package/full-service-imperative/app/models/Session.ts +14 -0
  292. package/full-service-imperative/app/models/User.ts +77 -0
  293. package/full-service-imperative/app/providers/DrizzleServiceProvider.ts +56 -0
  294. package/full-service-imperative/app/repositories/CommentRepository.ts +148 -0
  295. package/full-service-imperative/app/repositories/PostRepository.ts +130 -0
  296. package/full-service-imperative/app/repositories/SessionRepository.ts +115 -0
  297. package/full-service-imperative/app/repositories/UserRepository.ts +91 -0
  298. package/full-service-imperative/app/repositories/contracts/ICommentRepository.ts +72 -0
  299. package/full-service-imperative/app/repositories/contracts/IPostRepository.ts +63 -0
  300. package/full-service-imperative/app/repositories/contracts/ISessionRepository.ts +65 -0
  301. package/full-service-imperative/app/repositories/contracts/IUserRepository.ts +55 -0
  302. package/full-service-imperative/app/services/CommentService.ts +109 -0
  303. package/full-service-imperative/app/services/PostService.ts +97 -0
  304. package/full-service-imperative/app/services/SecurityService.ts +224 -0
  305. package/full-service-imperative/app/services/SessionService.ts +124 -0
  306. package/full-service-imperative/app/services/UserService.ts +105 -0
  307. package/full-service-imperative/app/services/contracts/ICommentService.ts +62 -0
  308. package/full-service-imperative/app/services/contracts/IPostService.ts +53 -0
  309. package/full-service-imperative/app/services/contracts/ISecurityService.ts +97 -0
  310. package/full-service-imperative/app/services/contracts/ISessionService.ts +73 -0
  311. package/full-service-imperative/app/services/contracts/IUserService.ts +57 -0
  312. package/full-service-imperative/app/subscribers/UserEventSubscriber.ts +28 -0
  313. package/full-service-imperative/drizzle.config.ts +13 -0
  314. package/full-service-imperative/package.json +48 -0
  315. package/full-service-imperative/stone.config.mjs +12 -0
  316. package/full-service-imperative/tsconfig.json +25 -0
  317. package/full-service-imperative/vitest.config.ts +24 -0
  318. package/package.json +225 -0
  319. package/standard-react-declarative/LICENSE +21 -0
  320. package/standard-react-declarative/README.md +39 -0
  321. package/standard-react-declarative/app/Application.ts +45 -0
  322. package/standard-react-declarative/app/pages/welcome/WelcomePage.tsx +57 -0
  323. package/standard-react-declarative/app/services/WelcomeService.ts +38 -0
  324. package/standard-react-declarative/assets/css/index.css +26 -0
  325. package/standard-react-declarative/package.json +42 -0
  326. package/standard-react-declarative/tsconfig.json +33 -0
  327. package/standard-react-declarative/vitest.config.ts +24 -0
  328. package/standard-react-imperative/LICENSE +21 -0
  329. package/standard-react-imperative/README.md +39 -0
  330. package/standard-react-imperative/app/Application.ts +41 -0
  331. package/standard-react-imperative/app/pages/welcome/WelcomePage.tsx +50 -0
  332. package/standard-react-imperative/app/services/WelcomeService.ts +38 -0
  333. package/standard-react-imperative/assets/css/index.css +26 -0
  334. package/standard-react-imperative/package.json +42 -0
  335. package/standard-react-imperative/tsconfig.json +33 -0
  336. package/standard-react-imperative/vitest.config.ts +24 -0
  337. package/standard-service-declarative/LICENSE +21 -0
  338. package/standard-service-declarative/README.md +39 -0
  339. package/standard-service-declarative/app/Application.ts +39 -0
  340. package/standard-service-declarative/app/handlers/WelcomeEventHandler.ts +45 -0
  341. package/standard-service-declarative/app/services/WelcomeService.ts +38 -0
  342. package/standard-service-declarative/package.json +36 -0
  343. package/standard-service-declarative/tsconfig.json +25 -0
  344. package/standard-service-declarative/vitest.config.ts +24 -0
  345. package/standard-service-imperative/LICENSE +21 -0
  346. package/standard-service-imperative/README.md +39 -0
  347. package/standard-service-imperative/app/Application.ts +11 -0
  348. package/standard-service-imperative/app/handlers/welcomeEventHandler.ts +31 -0
  349. package/standard-service-imperative/app/services/welcomeService.ts +38 -0
  350. package/standard-service-imperative/package.json +35 -0
  351. package/standard-service-imperative/tsconfig.json +25 -0
  352. package/standard-service-imperative/vitest.config.ts +24 -0
@@ -0,0 +1,33 @@
1
+ import { UserLogin, UserToken, UserRegister, UserChangePassword } from '../../models/User'
2
+
3
+ /**
4
+ * Security Client contract
5
+ */
6
+ export interface ISecurityClient {
7
+ /**
8
+ * Login a user.
9
+ *
10
+ * @param user - The user login credentials.
11
+ * @returns The access token.
12
+ */
13
+ login: (user: UserLogin) => Promise<UserToken>
14
+
15
+ /**
16
+ * Logout the currently authenticated user.
17
+ */
18
+ logout: () => Promise<void>
19
+
20
+ /**
21
+ * Register a new user.
22
+ *
23
+ * @param user - The user registration data.
24
+ */
25
+ register: (user: UserRegister) => Promise<void>
26
+
27
+ /**
28
+ * Change the password of the current user.
29
+ *
30
+ * @param password - The current and new password.
31
+ */
32
+ changePassword: (password: UserChangePassword) => Promise<void>
33
+ }
@@ -0,0 +1,61 @@
1
+ import { User, UserInput } from '../../models/User'
2
+
3
+ /**
4
+ * User Client contract
5
+ */
6
+ export interface IUserClient {
7
+ /**
8
+ * List users.
9
+ *
10
+ * @param limit - The limit of users to list (default: 10).
11
+ * @returns The list of users.
12
+ */
13
+ list: (limit?: number) => Promise<User[]>
14
+
15
+ /**
16
+ * Get the currently authenticated user.
17
+ *
18
+ * @returns The current user.
19
+ */
20
+ currentUser: () => Promise<User>
21
+
22
+ /**
23
+ * Find a user by ID.
24
+ *
25
+ * @param id - The ID of the user to find.
26
+ * @returns The found user.
27
+ */
28
+ find: (id: number) => Promise<User>
29
+
30
+ /**
31
+ * Create a new user.
32
+ *
33
+ * @param user - The user data to create.
34
+ * @returns The created user.
35
+ */
36
+ create: (user: UserInput) => Promise<User>
37
+
38
+ /**
39
+ * Update the currently authenticated user.
40
+ *
41
+ * @param user - The updated user data.
42
+ * @returns The updated user.
43
+ */
44
+ updateCurrent: (user: UserInput) => Promise<User>
45
+
46
+ /**
47
+ * Update a user by ID.
48
+ *
49
+ * @param id - The ID of the user to update.
50
+ * @param user - The updated user data.
51
+ * @returns The updated user.
52
+ */
53
+ update: (id: number, user: UserInput) => Promise<User>
54
+
55
+ /**
56
+ * Delete a user by ID.
57
+ *
58
+ * @param id - The ID of the user to delete.
59
+ */
60
+ delete: (id: number) => Promise<void>
61
+ }
@@ -0,0 +1,50 @@
1
+ import { FC, useRef } from 'react'
2
+ import { UserChangePassword } from '../../models/User'
3
+
4
+ /**
5
+ * Change Password Form Options
6
+ */
7
+ export interface ChangePasswordFormOptions {
8
+ onSubmit: (user: UserChangePassword) => Promise<void>
9
+ }
10
+
11
+ /**
12
+ * Change Password Form component.
13
+ *
14
+ * @param options - The options to create the Change Password Form component.
15
+ */
16
+ export const ChangePasswordForm: FC<ChangePasswordFormOptions> = ({ onSubmit }) => {
17
+ // Create a reference to the user
18
+ const userRef = useRef<UserChangePassword>({
19
+ password: '',
20
+ newPassword: '',
21
+ confirmPassword: ''
22
+ })
23
+
24
+ // Handle the form submit
25
+ const handleSubmit = (event: React.FormEvent<HTMLFormElement>): void => {
26
+ event.preventDefault()
27
+ void onSubmit(userRef.current).catch(() => {})
28
+ }
29
+
30
+ // Handle the field change
31
+ const onChange = (field: keyof UserChangePassword) => (event: React.ChangeEvent<HTMLInputElement>) => {
32
+ userRef.current[field] = event.target.value
33
+ }
34
+
35
+ // Render the component
36
+ return (
37
+ <form onSubmit={handleSubmit}>
38
+ <label htmlFor='password'>Current Password:</label>
39
+ <input id='password' type='password' onChange={onChange('password')} defaultValue={userRef.current.password} />
40
+
41
+ <label htmlFor='newPassword'>New Password:</label>
42
+ <input id='newPassword' type='password' onChange={onChange('newPassword')} defaultValue={userRef.current.newPassword} />
43
+
44
+ <label htmlFor='confirmPassword'>Confirm password:</label>
45
+ <input id='confirmPassword' type='password' onChange={onChange('confirmPassword')} defaultValue={userRef.current.confirmPassword} />
46
+
47
+ <button type='submit'>ChangePassword</button>
48
+ </form>
49
+ )
50
+ }
@@ -0,0 +1,35 @@
1
+ .comment-form {
2
+ gap: 0.5rem;
3
+ display: flex;
4
+ align-items: center;
5
+ }
6
+
7
+ .comment-input {
8
+ flex: 1;
9
+ padding: 0.5rem 0.75rem;
10
+ border-radius: 20px;
11
+ border: 1px solid #d1d5db;
12
+ background: #f9fafb;
13
+ font-size: 0.9rem;
14
+ outline: none;
15
+ }
16
+
17
+ .comment-input:focus {
18
+ border-color: #2563eb;
19
+ background-color: #fff;
20
+ }
21
+
22
+ .comment-submit {
23
+ background-color: #2563eb;
24
+ color: #fff;
25
+ border: none;
26
+ padding: 0.5rem 1rem;
27
+ border-radius: 20px;
28
+ cursor: pointer;
29
+ font-size: 0.85rem;
30
+ transition: background-color 0.2s ease;
31
+ }
32
+
33
+ .comment-submit:hover {
34
+ background-color: #1e3a8a;
35
+ }
@@ -0,0 +1,45 @@
1
+ import './CommentForm.css'
2
+ import { User } from '../../models/User'
3
+ import { FC, useRef, FormEvent } from 'react'
4
+ import { UserAvatar } from '../UserAvatar/UserAvatar'
5
+
6
+ /**
7
+ * CommentForm options.
8
+ */
9
+ export interface CommentFormOptions {
10
+ currentUser: User
11
+ onSubmit: (content: string) => Promise<void>
12
+ }
13
+
14
+ /**
15
+ * CommentForm component.
16
+ */
17
+ export const CommentForm: FC<CommentFormOptions> = ({ currentUser, onSubmit }) => {
18
+ const contentRef = useRef<HTMLInputElement>(null)
19
+
20
+ // Handle the form submit
21
+ const handleSubmit = (event: FormEvent<HTMLFormElement>): void => {
22
+ event.preventDefault()
23
+ if (contentRef.current === null) return
24
+
25
+ const content = contentRef.current.value.trim()
26
+ if (content.length === 0) return // Prevent empty submissions
27
+
28
+ contentRef.current.value = '' // Clear input field
29
+ void onSubmit(content).catch(() => {})
30
+ }
31
+
32
+ // Render the component
33
+ return (
34
+ <form className='comment-form' onSubmit={handleSubmit}>
35
+ <UserAvatar user={currentUser} />
36
+ <input
37
+ type='text'
38
+ ref={contentRef}
39
+ className='comment-input'
40
+ placeholder='Write a comment...'
41
+ />
42
+ <button className='comment-submit' type='submit'>Add Comment</button>
43
+ </form>
44
+ )
45
+ }
@@ -0,0 +1,74 @@
1
+ .comment-item {
2
+ display: flex;
3
+ align-items: flex-start;
4
+ gap: 0.75rem;
5
+ }
6
+
7
+ .comment-avatar {
8
+ width: 32px;
9
+ height: 32px;
10
+ border-radius: 50%;
11
+ object-fit: cover;
12
+ background-color: #f0f0f0;
13
+ }
14
+
15
+ .comment-bubble {
16
+ background: #f0f2f5;
17
+ border-radius: 12px;
18
+ padding: 0.5rem 0.75rem;
19
+ position: relative;
20
+ flex: 1;
21
+ }
22
+
23
+ .comment-meta {
24
+ display: flex;
25
+ justify-content: space-between;
26
+ font-size: 0.75rem;
27
+ color: #666;
28
+ margin-bottom: 0.25rem;
29
+ }
30
+
31
+ .comment-text {
32
+ font-size: 0.9rem;
33
+ color: #1c1e21;
34
+ line-height: 1.4;
35
+ }
36
+
37
+ .comment-delete {
38
+ position: absolute;
39
+ top: 6px;
40
+ right: 6px;
41
+ background: transparent;
42
+ border: none;
43
+ font-size: 0.9rem;
44
+ color: #999;
45
+ cursor: pointer;
46
+ }
47
+
48
+ .comment-delete:hover {
49
+ color: #e11d48;
50
+ }
51
+
52
+ .comment-reactions {
53
+ margin-top: 0.25rem;
54
+ }
55
+
56
+ .like-button {
57
+ background: none;
58
+ border: none;
59
+ color: #555;
60
+ font-size: 0.8rem;
61
+ cursor: pointer;
62
+ padding: 2px 6px;
63
+ border-radius: 6px;
64
+ transition: all 0.2s ease;
65
+ }
66
+
67
+ .like-button:hover {
68
+ background: #e5e7eb;
69
+ }
70
+
71
+ .like-button.liked {
72
+ color: #2563eb;
73
+ font-weight: 600;
74
+ }
@@ -0,0 +1,62 @@
1
+ import './CommentItem.css'
2
+ import { FC, useState } from 'react'
3
+ import { User } from '../../models/User'
4
+ import { dateTimeFromNow } from '../../utils'
5
+ import { CommentView } from '../../models/Comment'
6
+ import { UserAvatar } from '../UserAvatar/UserAvatar'
7
+
8
+ /**
9
+ * Comment Item Props
10
+ */
11
+ export interface CommentItemProps {
12
+ currentUser: User
13
+ commentView: CommentView
14
+ onToggleLike?: (comment: CommentView) => void
15
+ onDeleteComment?: (comment: CommentView) => void
16
+ onRetry: (commentView: CommentView) => Promise<void>
17
+ }
18
+
19
+ /**
20
+ * Comment Item component.
21
+ */
22
+ export const CommentItem: FC<CommentItemProps> = ({ currentUser, commentView, onRetry, onDeleteComment, onToggleLike }) => {
23
+ const [comment, setComment] = useState<CommentView>(commentView)
24
+
25
+ // Handle the retry
26
+ const handleOnClick = (): void => {
27
+ setComment({ ...comment, status: 'saving' })
28
+ void onRetry(comment).catch(() => {})
29
+ }
30
+
31
+ // Render the component
32
+ return (
33
+ <li key={comment.id} className='comment-item'>
34
+ <UserAvatar user={comment.author} size='sm' />
35
+ <div className='comment-bubble'>
36
+ <div className='comment-meta'>
37
+ <strong>{comment.author.name}</strong>
38
+ <span>{dateTimeFromNow(comment.createdAt)}</span>
39
+ </div>
40
+ <p className='comment-text'>{comment.content}</p>
41
+ {comment.author.id === currentUser.id && (onDeleteComment != null) && (
42
+ <button className='comment-delete' onClick={() => onDeleteComment(comment)}>✕</button>
43
+ )}
44
+ <div className='comment-reactions'>
45
+ <button
46
+ className={`like-button ${comment.likedByCurrentUser ? 'liked' : ''}`}
47
+ onClick={() => onToggleLike?.(comment)}
48
+ >
49
+ 👍 {comment.likesCount > 0 && <span>{comment.likesCount}</span>}
50
+ </button>
51
+ </div>
52
+ </div>
53
+ {comment.status === 'saving' && <p>Saving...</p>}
54
+ {comment.status === 'error' && (
55
+ <p>
56
+ <span>Error adding the comment!</span>
57
+ <button onClick={handleOnClick}>Retry</button>
58
+ </p>
59
+ )}
60
+ </li>
61
+ )
62
+ }
@@ -0,0 +1,25 @@
1
+ .comment-section {
2
+ margin-top: 1rem;
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 1rem;
6
+ }
7
+
8
+ .comment-list {
9
+ list-style: none;
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 0.75rem;
13
+ padding: 0;
14
+ margin: 0;
15
+ }
16
+
17
+ .show-more-comments {
18
+ background: none;
19
+ border: none;
20
+ color: #2563eb;
21
+ font-size: 0.85rem;
22
+ cursor: pointer;
23
+ margin-left: 2.5rem;
24
+ padding: 4px 8px;
25
+ }
@@ -0,0 +1,119 @@
1
+ import './CommentWidget.css'
2
+ import { User } from '../../models/User'
3
+ import { Post } from '../../models/Post'
4
+ import { FC, useEffect, useState } from 'react'
5
+ import { CommentItem } from '../CommentItem/CommentItem'
6
+ import { CommentForm } from '../CommentForm/CommentForm'
7
+ import { CommentInput, CommentView } from '../../models/Comment'
8
+ import { ICommentService } from '../../services/contracts/ICommentService'
9
+
10
+ /**
11
+ * Comment Widget Options
12
+ */
13
+ export interface CommentWidgetOptions {
14
+ post: Post
15
+ currentUser: User
16
+ commentService: ICommentService
17
+ }
18
+
19
+ /**
20
+ * Comment Items component.
21
+ */
22
+ export const CommentWidget: FC<CommentWidgetOptions> = ({ post, currentUser, commentService }) => {
23
+ const [limit, setLimit] = useState(10)
24
+ const [comments, setComments] = useState<CommentView[]>([])
25
+ const [showMoreComments, setShowMoreComments] = useState(false)
26
+ const [fetchingStatus, setFetchingStatus] = useState<'idle' | 'loading' | 'error'>('idle')
27
+
28
+ // Fetch comments
29
+ const fetchComments = async (): Promise<void> => {
30
+ try {
31
+ setFetchingStatus('loading')
32
+ const comments = await commentService.list(post.id, limit)
33
+ setFetchingStatus('idle')
34
+ setComments(comments)
35
+ setShowMoreComments(comments.length < post.commentsCount)
36
+ } catch (_: any) {
37
+ setFetchingStatus('error')
38
+ }
39
+ }
40
+
41
+ const fetchMoreComments = (): void => {
42
+ setLimit(limit + 10)
43
+ setShowMoreComments(false)
44
+ void fetchComments().catch(() => {})
45
+ }
46
+
47
+ // Save comment
48
+ const saveComment = async (commentInput: CommentInput): Promise<void> => {
49
+ try {
50
+ await commentService.create(post.id, commentInput)
51
+ await fetchComments()
52
+ } catch (_: any) {
53
+ setComments(comments.map(comment => ({
54
+ ...comment,
55
+ status: comment.id === commentInput.id ? 'error' : comment.status
56
+ })))
57
+ }
58
+ }
59
+
60
+ // Handle save
61
+ const handleOnSubmit = async (content: string): Promise<void> => {
62
+ const id = Math.random()
63
+ const commentInput: CommentInput = {
64
+ id,
65
+ content,
66
+ likesCount: 0,
67
+ postId: post.id,
68
+ likedByCurrentUser: false
69
+ }
70
+
71
+ const commentView: CommentView = {
72
+ ...commentInput,
73
+ author: currentUser,
74
+ status: 'saving',
75
+ createdAt: Date.now()
76
+ }
77
+
78
+ setComments([...comments, commentView])
79
+
80
+ await saveComment(commentInput)
81
+ }
82
+
83
+ // Fetch comments on mount
84
+ useEffect(() => { fetchComments().then(() => {}).catch(() => {}) }, [post.id])
85
+
86
+ // Render
87
+ if (comments.length === 0 && fetchingStatus === 'loading') {
88
+ return <p className='comment-loading'>Loading comments...</p>
89
+ } else if (comments.length === 0 && fetchingStatus === 'error') {
90
+ return <p className='comment-error'>Error fetching comments</p>
91
+ } else {
92
+ return (
93
+ <div className='comment-section'>
94
+ <CommentForm
95
+ currentUser={currentUser}
96
+ onSubmit={handleOnSubmit}
97
+ />
98
+ <ul className='comment-list'>
99
+ {comments.map((comment) => (
100
+ <CommentItem
101
+ key={comment.id}
102
+ currentUser={currentUser}
103
+ commentView={comment}
104
+ onRetry={saveComment}
105
+ />
106
+ ))}
107
+ </ul>
108
+ {showMoreComments && (
109
+ <button
110
+ className='show-more-comments'
111
+ onClick={() => fetchMoreComments()}
112
+ >
113
+ Show more comments
114
+ </button>
115
+ )}
116
+ </div>
117
+ )
118
+ }
119
+ }
@@ -0,0 +1,52 @@
1
+ .dropdown-wrapper {
2
+ position: relative;
3
+ }
4
+
5
+ .dropdown-container {
6
+ top: 100%;
7
+ opacity: 0;
8
+ z-index: 100;
9
+ min-width: 180px;
10
+ position: absolute;
11
+ margin-top: 0.5rem;
12
+ border-radius: 8px;
13
+ background: white;
14
+ pointer-events: none;
15
+ transform: scale(0.98);
16
+ transition: all 0.2s ease;
17
+ border: 1px solid #e5e7eb;
18
+ box-shadow: 0 4px 12px rgba(0,0,0,0.05);
19
+ }
20
+
21
+ .dropdown-container.open {
22
+ opacity: 1;
23
+ transform: scale(1);
24
+ pointer-events: auto;
25
+ }
26
+
27
+ .dropdown-container.closed {
28
+ display: none;
29
+ }
30
+
31
+ .dropdown-container.right {
32
+ right: 0;
33
+ }
34
+
35
+ .dropdown-container.left {
36
+ left: 0;
37
+ }
38
+
39
+ .dropdown-container ul {
40
+ list-style: none;
41
+ padding: 0.25rem 0;
42
+ }
43
+
44
+ .dropdown-container li {
45
+ padding: 0.5rem 1rem;
46
+ font-size: 0.9rem;
47
+ cursor: pointer;
48
+ }
49
+
50
+ .dropdown-container li:hover {
51
+ background: #f3f4f6;
52
+ }
@@ -0,0 +1,40 @@
1
+ import './Dropdown.css'
2
+ import { FC, ReactNode, useEffect, useRef } from 'react'
3
+
4
+ interface DropdownOptions {
5
+ show: boolean
6
+ className?: string
7
+ children: ReactNode
8
+ onClose: () => void
9
+ align?: 'left' | 'right'
10
+ }
11
+
12
+ export const Dropdown: FC<DropdownOptions> = ({
13
+ show,
14
+ onClose,
15
+ children,
16
+ align = 'right',
17
+ className = ''
18
+ }) => {
19
+ const ref = useRef<HTMLDivElement>(null)
20
+
21
+ useEffect(() => {
22
+ const handleClickOutside = (e: MouseEvent): void => {
23
+ const target = e.target as HTMLElement
24
+ if (ref.current?.contains(target) !== true && (target.closest('.dropdown-wrapper') == null)) {
25
+ onClose()
26
+ }
27
+ }
28
+ document.addEventListener('mousedown', handleClickOutside)
29
+ return () => document.removeEventListener('mousedown', handleClickOutside)
30
+ }, [onClose])
31
+
32
+ return (
33
+ <div
34
+ ref={ref}
35
+ className={`dropdown-container ${align} ${show ? 'open' : 'closed'} ${className}`}
36
+ >
37
+ {children}
38
+ </div>
39
+ )
40
+ }
@@ -0,0 +1,62 @@
1
+ .app-header .app-navbar {
2
+ display: flex;
3
+ margin: 0 auto;
4
+ max-width: 1280px;
5
+ align-items: center;
6
+ padding: 0.75rem 1.5rem;
7
+ justify-content: space-between;
8
+ }
9
+
10
+ .header-left .logo {
11
+ margin: 0;
12
+ gap: 0.5rem;
13
+ border: none;
14
+ display: flex;
15
+ color: #1c1e21;
16
+ background: none;
17
+ font-weight: bold;
18
+ font-size: 1.25rem;
19
+ align-items: center;
20
+ text-decoration: none;
21
+ }
22
+
23
+ .header-left .logo:hover {
24
+ cursor: pointer;
25
+ }
26
+
27
+ .header-left img {
28
+ height: 36px;
29
+ width: 36px;
30
+ }
31
+
32
+ .header-left .logo span {
33
+ font-size: 1.1em;
34
+ margin-left: 8px;
35
+ font-weight: bold;
36
+ }
37
+
38
+ .header-right {
39
+ gap: 3rem;
40
+ display: flex;
41
+ align-items: center;
42
+ }
43
+
44
+ .user-info {
45
+ display: flex;
46
+ align-items: center;
47
+ gap: 0.5rem;
48
+ }
49
+
50
+ .avatar {
51
+ width: 36px;
52
+ height: 36px;
53
+ border-radius: 50%;
54
+ object-fit: cover;
55
+ }
56
+
57
+ .user-details {
58
+ display: flex;
59
+ flex-direction: column;
60
+ font-size: 0.875rem;
61
+ color: #555;
62
+ }