@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.
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/basic-react-declarative/LICENSE +21 -0
- package/basic-react-declarative/README.md +39 -0
- package/basic-react-declarative/app/Application.tsx +89 -0
- package/basic-react-declarative/assets/css/index.css +26 -0
- package/basic-react-declarative/package.json +39 -0
- package/basic-react-declarative/public/logo.png +0 -0
- package/basic-react-declarative/tests/Application.spec.ts +96 -0
- package/basic-react-declarative/tests/__snapshots__/Application.spec.ts.snap +3 -0
- package/basic-react-declarative/tsconfig.json +33 -0
- package/basic-react-declarative/vitest.config.ts +24 -0
- package/basic-react-imperative/LICENSE +21 -0
- package/basic-react-imperative/README.md +39 -0
- package/basic-react-imperative/app/Application.tsx +89 -0
- package/basic-react-imperative/assets/css/index.css +26 -0
- package/basic-react-imperative/package.json +39 -0
- package/basic-react-imperative/public/logo.png +0 -0
- package/basic-react-imperative/tests/Application.spec.ts +80 -0
- package/basic-react-imperative/tests/__snapshots__/Application.spec.ts.snap +3 -0
- package/basic-react-imperative/tsconfig.json +33 -0
- package/basic-react-imperative/vitest.config.ts +24 -0
- package/basic-service-declarative/LICENSE +21 -0
- package/basic-service-declarative/README.md +39 -0
- package/basic-service-declarative/app/Application.ts +56 -0
- package/basic-service-declarative/package.json +34 -0
- package/basic-service-declarative/tests/Application.spec.ts +60 -0
- package/basic-service-declarative/tsconfig.json +25 -0
- package/basic-service-declarative/vitest.config.ts +24 -0
- package/basic-service-imperative/LICENSE +21 -0
- package/basic-service-imperative/README.md +39 -0
- package/basic-service-imperative/app/Application.ts +60 -0
- package/basic-service-imperative/package.json +34 -0
- package/basic-service-imperative/tests/Application.spec.ts +52 -0
- package/basic-service-imperative/tsconfig.json +25 -0
- package/basic-service-imperative/vitest.config.ts +24 -0
- package/continuum-showcase/README.md +44 -0
- package/continuum-showcase/app/env.d.ts +34 -0
- package/continuum-showcase/app/layouts/MainLayout.tsx +20 -0
- package/continuum-showcase/app/pages/BlogPostPage.tsx +62 -0
- package/continuum-showcase/app/pages/HomePage.tsx +58 -0
- package/continuum-showcase/package.json +25 -0
- package/continuum-showcase/stone.config.mjs +20 -0
- package/full-react-declarative/.env.example +1 -0
- package/full-react-declarative/.env.public.example +1 -0
- package/full-react-declarative/LICENSE +21 -0
- package/full-react-declarative/README.md +39 -0
- package/full-react-declarative/app/Application.ts +85 -0
- package/full-react-declarative/app/clients/AxiosClient.ts +136 -0
- package/full-react-declarative/app/clients/CommentClient.ts +61 -0
- package/full-react-declarative/app/clients/PostClient.ts +90 -0
- package/full-react-declarative/app/clients/SecurityClient.ts +66 -0
- package/full-react-declarative/app/clients/UserClient.ts +97 -0
- package/full-react-declarative/app/components/ChangePasswordForm/ChangePasswordForm.tsx +50 -0
- package/full-react-declarative/app/components/CommentForm/CommentForm.tsx +37 -0
- package/full-react-declarative/app/components/CommentItem/CommentItem.tsx +42 -0
- package/full-react-declarative/app/components/CommentWidget/CommentWidget.tsx +95 -0
- package/full-react-declarative/app/components/LoginForm/LoginForm.css +0 -0
- package/full-react-declarative/app/components/LoginForm/LoginForm.tsx +71 -0
- package/full-react-declarative/app/components/PostDetails/PostDetails.tsx +44 -0
- package/full-react-declarative/app/components/PostForm/PostForm.css +0 -0
- package/full-react-declarative/app/components/PostForm/PostForm.tsx +47 -0
- package/full-react-declarative/app/components/PostItem/PostItem.css +0 -0
- package/full-react-declarative/app/components/PostItem/PostItem.tsx +34 -0
- package/full-react-declarative/app/components/RegisterForm/RegisterForm.tsx +110 -0
- package/full-react-declarative/app/components/UserForm/UserForm.tsx +47 -0
- package/full-react-declarative/app/configurations/AppConfiguration.ts +17 -0
- package/full-react-declarative/app/error-pages/DefaultErrorPage/DefaultErrorPage.css +0 -0
- package/full-react-declarative/app/error-pages/DefaultErrorPage/DefaultErrorPage.tsx +52 -0
- package/full-react-declarative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.css +0 -0
- package/full-react-declarative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.tsx +53 -0
- package/full-react-declarative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.css +0 -0
- package/full-react-declarative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.tsx +54 -0
- package/full-react-declarative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.css +0 -0
- package/full-react-declarative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.tsx +53 -0
- package/full-react-declarative/app/errors/ForbiddenError.ts +11 -0
- package/full-react-declarative/app/errors/PostNotFoundError.ts +11 -0
- package/full-react-declarative/app/errors/UnauthorizedError.ts +11 -0
- package/full-react-declarative/app/errors/UserNotFoundError.ts +11 -0
- package/full-react-declarative/app/events/UserEvent.ts +18 -0
- package/full-react-declarative/app/layout/AppLayout/AppLayout.css +20 -0
- package/full-react-declarative/app/layout/AppLayout/AppLayout.tsx +101 -0
- package/full-react-declarative/app/layout/ErrorLayout/ErrorLayout.css +0 -0
- package/full-react-declarative/app/layout/ErrorLayout/ErrorLayout.tsx +41 -0
- package/full-react-declarative/app/layout/SecurityLayout/SecurityLayout.css +0 -0
- package/full-react-declarative/app/layout/SecurityLayout/SecurityLayout.tsx +39 -0
- package/full-react-declarative/app/middleware/AuthMiddleware.ts +85 -0
- package/full-react-declarative/app/models/Comment.ts +31 -0
- package/full-react-declarative/app/models/Post.ts +22 -0
- package/full-react-declarative/app/models/User.ts +62 -0
- package/full-react-declarative/app/pages/home/HomePage.tsx +44 -0
- package/full-react-declarative/app/pages/login/LoginPage.css +0 -0
- package/full-react-declarative/app/pages/login/LoginPage.tsx +73 -0
- package/full-react-declarative/app/pages/posts/CreatePostPage/CreatePostPage.css +0 -0
- package/full-react-declarative/app/pages/posts/CreatePostPage/CreatePostPage.tsx +67 -0
- package/full-react-declarative/app/pages/posts/PostPage/PostPage.tsx +60 -0
- package/full-react-declarative/app/pages/posts/ShowPostPage/ShowPostPage.tsx +83 -0
- package/full-react-declarative/app/pages/posts/UpdatePostPage/UpdatePostPage.tsx +77 -0
- package/full-react-declarative/app/pages/register/RegisterPage.tsx +68 -0
- package/full-react-declarative/app/pages/users/CreateUserPage.tsx +48 -0
- package/full-react-declarative/app/pages/users/ShowUserPage.tsx +62 -0
- package/full-react-declarative/app/pages/users/UpdateUserPage.tsx +57 -0
- package/full-react-declarative/app/pages/users/UserPage.tsx +57 -0
- package/full-react-declarative/app/providers/AppServiceProvider.ts +43 -0
- package/full-react-declarative/app/services/CommentService.ts +59 -0
- package/full-react-declarative/app/services/PostService.ts +108 -0
- package/full-react-declarative/app/services/SecurityService.ts +80 -0
- package/full-react-declarative/app/services/TokenService.ts +116 -0
- package/full-react-declarative/app/services/UserService.ts +126 -0
- package/full-react-declarative/app/utils.ts +17 -0
- package/full-react-declarative/assets/css/index.css +301 -0
- package/full-react-declarative/assets/img/logo.png +0 -0
- package/full-react-declarative/package.json +46 -0
- package/full-react-declarative/public/logo.png +0 -0
- package/full-react-declarative/public/vite.svg +1 -0
- package/full-react-declarative/stone.config.mjs +12 -0
- package/full-react-declarative/tsconfig.json +29 -0
- package/full-react-declarative/vitest.config.ts +24 -0
- package/full-react-imperative/.env.example +1 -0
- package/full-react-imperative/.env.public.example +1 -0
- package/full-react-imperative/LICENSE +21 -0
- package/full-react-imperative/README.md +39 -0
- package/full-react-imperative/app/Application.ts +79 -0
- package/full-react-imperative/app/clients/AxiosClient.ts +124 -0
- package/full-react-imperative/app/clients/CommentClient.ts +57 -0
- package/full-react-imperative/app/clients/PostClient.ts +86 -0
- package/full-react-imperative/app/clients/SecurityClient.ts +60 -0
- package/full-react-imperative/app/clients/UserClient.ts +93 -0
- package/full-react-imperative/app/clients/contracts/IAxiosClient.ts +97 -0
- package/full-react-imperative/app/clients/contracts/ICommentClient.ts +31 -0
- package/full-react-imperative/app/clients/contracts/IPostClient.ts +55 -0
- package/full-react-imperative/app/clients/contracts/ISecurityClient.ts +33 -0
- package/full-react-imperative/app/clients/contracts/IUserClient.ts +61 -0
- package/full-react-imperative/app/components/ChangePasswordForm/ChangePasswordForm.tsx +50 -0
- package/full-react-imperative/app/components/CommentForm/CommentForm.css +35 -0
- package/full-react-imperative/app/components/CommentForm/CommentForm.tsx +45 -0
- package/full-react-imperative/app/components/CommentItem/CommentItem.css +74 -0
- package/full-react-imperative/app/components/CommentItem/CommentItem.tsx +62 -0
- package/full-react-imperative/app/components/CommentWidget/CommentWidget.css +25 -0
- package/full-react-imperative/app/components/CommentWidget/CommentWidget.tsx +119 -0
- package/full-react-imperative/app/components/Dropdown/Dropdown.css +52 -0
- package/full-react-imperative/app/components/Dropdown/Dropdown.tsx +40 -0
- package/full-react-imperative/app/components/LayoutHeader/LayoutHeader.css +62 -0
- package/full-react-imperative/app/components/LayoutHeader/LayoutHeader.tsx +61 -0
- package/full-react-imperative/app/components/LayoutLeftMenu/LayoutLeftMenu.css +25 -0
- package/full-react-imperative/app/components/LayoutLeftMenu/LayoutLeftMenu.tsx +32 -0
- package/full-react-imperative/app/components/LoginForm/LoginForm.css +0 -0
- package/full-react-imperative/app/components/LoginForm/LoginForm.tsx +71 -0
- package/full-react-imperative/app/components/NotificationBadge/NotificationBadge.css +41 -0
- package/full-react-imperative/app/components/NotificationBadge/NotificationBadge.tsx +63 -0
- package/full-react-imperative/app/components/PostCard/PostCard.css +129 -0
- package/full-react-imperative/app/components/PostCard/PostCard.tsx +65 -0
- package/full-react-imperative/app/components/PostForm/PostForm.css +92 -0
- package/full-react-imperative/app/components/PostForm/PostForm.tsx +76 -0
- package/full-react-imperative/app/components/PostSkeleton/PostSkeleton.css +65 -0
- package/full-react-imperative/app/components/PostSkeleton/PostSkeleton.tsx +25 -0
- package/full-react-imperative/app/components/PostWidget/PostWidget.tsx +95 -0
- package/full-react-imperative/app/components/ProfileForm/ProfileForm.css +84 -0
- package/full-react-imperative/app/components/ProfileForm/ProfileForm.tsx +79 -0
- package/full-react-imperative/app/components/RegisterForm/RegisterForm.tsx +110 -0
- package/full-react-imperative/app/components/RightAsidePanel/RightAsidePanel.css +32 -0
- package/full-react-imperative/app/components/RightAsidePanel/RightAsidePanel.tsx +62 -0
- package/full-react-imperative/app/components/SettingsForm/SettingsForm.css +126 -0
- package/full-react-imperative/app/components/SettingsForm/SettingsForm.tsx +86 -0
- package/full-react-imperative/app/components/UserAvatar/UserAvatar.css +18 -0
- package/full-react-imperative/app/components/UserAvatar/UserAvatar.tsx +60 -0
- package/full-react-imperative/app/components/UserBadge/UserBadge.css +33 -0
- package/full-react-imperative/app/components/UserBadge/UserBadge.tsx +49 -0
- package/full-react-imperative/app/components/UserCard/UserCard.css +70 -0
- package/full-react-imperative/app/components/UserCard/UserCard.tsx +43 -0
- package/full-react-imperative/app/configurations/AppConfiguration.ts +19 -0
- package/full-react-imperative/app/error-pages/DefaultErrorPage/DefaultErrorPage.css +0 -0
- package/full-react-imperative/app/error-pages/DefaultErrorPage/DefaultErrorPage.tsx +41 -0
- package/full-react-imperative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.css +0 -0
- package/full-react-imperative/app/error-pages/ForbiddenErrorPage/ForbiddenErrorPage.tsx +42 -0
- package/full-react-imperative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.css +0 -0
- package/full-react-imperative/app/error-pages/NotFoundErrorPage/NotFoundErrorPage.tsx +49 -0
- package/full-react-imperative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.css +0 -0
- package/full-react-imperative/app/error-pages/UnauthorizedErrorPage/UnauthorizedErrorPage.tsx +42 -0
- package/full-react-imperative/app/errors/ForbiddenError.ts +11 -0
- package/full-react-imperative/app/errors/PostNotFoundError.ts +11 -0
- package/full-react-imperative/app/errors/UnauthorizedError.ts +11 -0
- package/full-react-imperative/app/errors/UserNotFoundError.ts +11 -0
- package/full-react-imperative/app/events/UserEvent.ts +18 -0
- package/full-react-imperative/app/layout/AppLayout/AppLayout.css +106 -0
- package/full-react-imperative/app/layout/AppLayout/AppLayout.tsx +48 -0
- package/full-react-imperative/app/layout/ErrorLayout/ErrorLayout.css +0 -0
- package/full-react-imperative/app/layout/ErrorLayout/ErrorLayout.tsx +45 -0
- package/full-react-imperative/app/layout/SecurityLayout/SecurityLayout.css +0 -0
- package/full-react-imperative/app/layout/SecurityLayout/SecurityLayout.tsx +43 -0
- package/full-react-imperative/app/layout/SettingsLayout/SettingsLayout.css +99 -0
- package/full-react-imperative/app/layout/SettingsLayout/SettingsLayout.tsx +44 -0
- package/full-react-imperative/app/middleware/AuthMiddleware.ts +56 -0
- package/full-react-imperative/app/models/Comment.ts +35 -0
- package/full-react-imperative/app/models/Post.ts +27 -0
- package/full-react-imperative/app/models/User.ts +68 -0
- package/full-react-imperative/app/pages/Settings/SettingsPage.tsx +23 -0
- package/full-react-imperative/app/pages/home/HomePage.tsx +58 -0
- package/full-react-imperative/app/pages/login/LoginPage.css +0 -0
- package/full-react-imperative/app/pages/login/LoginPage.tsx +65 -0
- package/full-react-imperative/app/pages/posts/ShowPostPage/ShowPostPage.tsx +64 -0
- package/full-react-imperative/app/pages/posts/UpdatePostPage/UpdatePostPage.tsx +56 -0
- package/full-react-imperative/app/pages/register/RegisterPage.tsx +71 -0
- package/full-react-imperative/app/pages/users/ShowUserPage/ShowUserPage.css +64 -0
- package/full-react-imperative/app/pages/users/ShowUserPage/ShowUserPage.tsx +104 -0
- package/full-react-imperative/app/pages/users/UpdateUserPage/UpdateUserPage.css +0 -0
- package/full-react-imperative/app/pages/users/UpdateUserPage/UpdateUserPage.tsx +43 -0
- package/full-react-imperative/app/pages/users/UserPage/UserPage.css +31 -0
- package/full-react-imperative/app/pages/users/UserPage/UserPage.tsx +59 -0
- package/full-react-imperative/app/pages/utils.ts +67 -0
- package/full-react-imperative/app/providers/AppServiceProvider.ts +40 -0
- package/full-react-imperative/app/services/CommentService.ts +53 -0
- package/full-react-imperative/app/services/PostService.ts +102 -0
- package/full-react-imperative/app/services/SecurityService.ts +72 -0
- package/full-react-imperative/app/services/TokenService.ts +108 -0
- package/full-react-imperative/app/services/UserService.ts +115 -0
- package/full-react-imperative/app/services/contracts/ICommentService.ts +30 -0
- package/full-react-imperative/app/services/contracts/IPostService.ts +65 -0
- package/full-react-imperative/app/services/contracts/ISecurityService.ts +39 -0
- package/full-react-imperative/app/services/contracts/ITokenService.ts +44 -0
- package/full-react-imperative/app/services/contracts/IUserService.ts +70 -0
- package/full-react-imperative/app/utils.ts +31 -0
- package/full-react-imperative/assets/css/index.css +301 -0
- package/full-react-imperative/assets/img/logo.png +0 -0
- package/full-react-imperative/package.json +48 -0
- package/full-react-imperative/public/logo.png +0 -0
- package/full-react-imperative/public/vite.svg +1 -0
- package/full-react-imperative/stone.config.mjs +12 -0
- package/full-react-imperative/tsconfig.json +29 -0
- package/full-react-imperative/vitest.config.ts +24 -0
- package/full-service-declarative/.env.example +2 -0
- package/full-service-declarative/LICENSE +21 -0
- package/full-service-declarative/README.md +65 -0
- package/full-service-declarative/app/Application.ts +327 -0
- package/full-service-declarative/app/commands/ListSessionsCommand.ts +70 -0
- package/full-service-declarative/app/commands/ListUsersCommand.ts +56 -0
- package/full-service-declarative/app/configurations/AppConfiguration.ts +52 -0
- package/full-service-declarative/app/configurations/UserLiveConfiguration.ts +28 -0
- package/full-service-declarative/app/database/DatabaseClient.ts +43 -0
- package/full-service-declarative/app/database/schema.ts +43 -0
- package/full-service-declarative/app/error-handlers/SecurityErrorHandler.ts +61 -0
- package/full-service-declarative/app/errors/CredentialsError.ts +12 -0
- package/full-service-declarative/app/events/UserEvent.ts +17 -0
- package/full-service-declarative/app/handlers/CommentEventHandler.ts +103 -0
- package/full-service-declarative/app/handlers/PostEventHandler.ts +104 -0
- package/full-service-declarative/app/handlers/SecurityEventHandler.ts +108 -0
- package/full-service-declarative/app/handlers/UserEventHandler.ts +159 -0
- package/full-service-declarative/app/listeners/UserEventListener.ts +35 -0
- package/full-service-declarative/app/middleware/AuthMiddleware.ts +54 -0
- package/full-service-declarative/app/models/Comment.ts +38 -0
- package/full-service-declarative/app/models/Post.ts +50 -0
- package/full-service-declarative/app/models/Session.ts +14 -0
- package/full-service-declarative/app/models/User.ts +77 -0
- package/full-service-declarative/app/providers/DrizzleServiceProvider.ts +59 -0
- package/full-service-declarative/app/repositories/CommentRepository.ts +155 -0
- package/full-service-declarative/app/repositories/PostRepository.ts +138 -0
- package/full-service-declarative/app/repositories/SessionRepository.ts +123 -0
- package/full-service-declarative/app/repositories/UserRepository.ts +99 -0
- package/full-service-declarative/app/services/CommentService.ts +112 -0
- package/full-service-declarative/app/services/PostService.ts +100 -0
- package/full-service-declarative/app/services/SecurityService.ts +232 -0
- package/full-service-declarative/app/services/SessionService.ts +130 -0
- package/full-service-declarative/app/services/UserService.ts +110 -0
- package/full-service-declarative/app/subscribers/UserEventSubscriber.ts +38 -0
- package/full-service-declarative/drizzle.config.ts +13 -0
- package/full-service-declarative/package.json +48 -0
- package/full-service-declarative/stone.config.mjs +12 -0
- package/full-service-declarative/tsconfig.json +25 -0
- package/full-service-declarative/vitest.config.ts +24 -0
- package/full-service-imperative/.env.example +2 -0
- package/full-service-imperative/LICENSE +21 -0
- package/full-service-imperative/README.md +65 -0
- package/full-service-imperative/app/Application.ts +317 -0
- package/full-service-imperative/app/commands/ListSessionsCommand.ts +54 -0
- package/full-service-imperative/app/commands/ListUsersCommand.ts +42 -0
- package/full-service-imperative/app/configurations/AppConfiguration.ts +44 -0
- package/full-service-imperative/app/configurations/UserLiveConfiguration.ts +26 -0
- package/full-service-imperative/app/database/DatabaseClient.ts +39 -0
- package/full-service-imperative/app/database/schema.ts +43 -0
- package/full-service-imperative/app/error-handlers/SecurityErrorHandler.ts +58 -0
- package/full-service-imperative/app/errors/CredentialsError.ts +12 -0
- package/full-service-imperative/app/events/UserEvent.ts +17 -0
- package/full-service-imperative/app/handlers/CommentEventHandler.ts +99 -0
- package/full-service-imperative/app/handlers/PostEventHandler.ts +99 -0
- package/full-service-imperative/app/handlers/SecurityEventHandler.ts +83 -0
- package/full-service-imperative/app/handlers/UserEventHandler.ts +132 -0
- package/full-service-imperative/app/listeners/UserEventListener.ts +23 -0
- package/full-service-imperative/app/middleware/AuthMiddleware.ts +44 -0
- package/full-service-imperative/app/models/Comment.ts +38 -0
- package/full-service-imperative/app/models/Post.ts +50 -0
- package/full-service-imperative/app/models/Session.ts +14 -0
- package/full-service-imperative/app/models/User.ts +77 -0
- package/full-service-imperative/app/providers/DrizzleServiceProvider.ts +56 -0
- package/full-service-imperative/app/repositories/CommentRepository.ts +148 -0
- package/full-service-imperative/app/repositories/PostRepository.ts +130 -0
- package/full-service-imperative/app/repositories/SessionRepository.ts +115 -0
- package/full-service-imperative/app/repositories/UserRepository.ts +91 -0
- package/full-service-imperative/app/repositories/contracts/ICommentRepository.ts +72 -0
- package/full-service-imperative/app/repositories/contracts/IPostRepository.ts +63 -0
- package/full-service-imperative/app/repositories/contracts/ISessionRepository.ts +65 -0
- package/full-service-imperative/app/repositories/contracts/IUserRepository.ts +55 -0
- package/full-service-imperative/app/services/CommentService.ts +109 -0
- package/full-service-imperative/app/services/PostService.ts +97 -0
- package/full-service-imperative/app/services/SecurityService.ts +224 -0
- package/full-service-imperative/app/services/SessionService.ts +124 -0
- package/full-service-imperative/app/services/UserService.ts +105 -0
- package/full-service-imperative/app/services/contracts/ICommentService.ts +62 -0
- package/full-service-imperative/app/services/contracts/IPostService.ts +53 -0
- package/full-service-imperative/app/services/contracts/ISecurityService.ts +97 -0
- package/full-service-imperative/app/services/contracts/ISessionService.ts +73 -0
- package/full-service-imperative/app/services/contracts/IUserService.ts +57 -0
- package/full-service-imperative/app/subscribers/UserEventSubscriber.ts +28 -0
- package/full-service-imperative/drizzle.config.ts +13 -0
- package/full-service-imperative/package.json +48 -0
- package/full-service-imperative/stone.config.mjs +12 -0
- package/full-service-imperative/tsconfig.json +25 -0
- package/full-service-imperative/vitest.config.ts +24 -0
- package/package.json +225 -0
- package/standard-react-declarative/LICENSE +21 -0
- package/standard-react-declarative/README.md +39 -0
- package/standard-react-declarative/app/Application.ts +45 -0
- package/standard-react-declarative/app/pages/welcome/WelcomePage.tsx +57 -0
- package/standard-react-declarative/app/services/WelcomeService.ts +38 -0
- package/standard-react-declarative/assets/css/index.css +26 -0
- package/standard-react-declarative/package.json +42 -0
- package/standard-react-declarative/tsconfig.json +33 -0
- package/standard-react-declarative/vitest.config.ts +24 -0
- package/standard-react-imperative/LICENSE +21 -0
- package/standard-react-imperative/README.md +39 -0
- package/standard-react-imperative/app/Application.ts +41 -0
- package/standard-react-imperative/app/pages/welcome/WelcomePage.tsx +50 -0
- package/standard-react-imperative/app/services/WelcomeService.ts +38 -0
- package/standard-react-imperative/assets/css/index.css +26 -0
- package/standard-react-imperative/package.json +42 -0
- package/standard-react-imperative/tsconfig.json +33 -0
- package/standard-react-imperative/vitest.config.ts +24 -0
- package/standard-service-declarative/LICENSE +21 -0
- package/standard-service-declarative/README.md +39 -0
- package/standard-service-declarative/app/Application.ts +39 -0
- package/standard-service-declarative/app/handlers/WelcomeEventHandler.ts +45 -0
- package/standard-service-declarative/app/services/WelcomeService.ts +38 -0
- package/standard-service-declarative/package.json +36 -0
- package/standard-service-declarative/tsconfig.json +25 -0
- package/standard-service-declarative/vitest.config.ts +24 -0
- package/standard-service-imperative/LICENSE +21 -0
- package/standard-service-imperative/README.md +39 -0
- package/standard-service-imperative/app/Application.ts +11 -0
- package/standard-service-imperative/app/handlers/welcomeEventHandler.ts +31 -0
- package/standard-service-imperative/app/services/welcomeService.ts +38 -0
- package/standard-service-imperative/package.json +35 -0
- package/standard-service-imperative/tsconfig.json +25 -0
- package/standard-service-imperative/vitest.config.ts +24 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Event } from '@stone-js/core'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* User Event
|
|
5
|
+
*/
|
|
6
|
+
export class UserEvent extends Event {
|
|
7
|
+
/**
|
|
8
|
+
* USER_CREATED Event name, fires after a user have been created.
|
|
9
|
+
*
|
|
10
|
+
* @event UserEvent#USER_CREATED
|
|
11
|
+
*/
|
|
12
|
+
static USER_CREATED: string = 'user.created'
|
|
13
|
+
|
|
14
|
+
constructor (public readonly user: any) {
|
|
15
|
+
super({ type: UserEvent.USER_CREATED })
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { User } from '../models/User'
|
|
2
|
+
import { ILogger } from '@stone-js/core'
|
|
3
|
+
import { Post as BlogPost } from '../models/Post'
|
|
4
|
+
import { PostService } from '../services/PostService'
|
|
5
|
+
import { CommentService } from '../services/CommentService'
|
|
6
|
+
import { CommentModel, CommentResponse } from '../models/Comment'
|
|
7
|
+
import { Delete, EventHandler, Get, Post } from '@stone-js/router'
|
|
8
|
+
import { IncomingHttpEvent, JsonHttpResponse } from '@stone-js/http-core'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Comment Event Handler Options
|
|
12
|
+
*/
|
|
13
|
+
export interface CommentEventHandlerOptions {
|
|
14
|
+
logger: ILogger
|
|
15
|
+
commentService: CommentService
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Comment Event Handler
|
|
20
|
+
*
|
|
21
|
+
* Handles comment-related HTTP events.
|
|
22
|
+
*/
|
|
23
|
+
@EventHandler('/comments', { name: 'comments' })
|
|
24
|
+
export class CommentEventHandler {
|
|
25
|
+
private readonly logger: ILogger
|
|
26
|
+
private readonly commentService: CommentService
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a new instance of CommentEventHandler
|
|
30
|
+
*
|
|
31
|
+
* @param commentService
|
|
32
|
+
* @param logger
|
|
33
|
+
*/
|
|
34
|
+
constructor ({ commentService, logger }: CommentEventHandlerOptions) {
|
|
35
|
+
this.logger = logger
|
|
36
|
+
this.commentService = commentService
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* List all comments
|
|
41
|
+
*/
|
|
42
|
+
@Get('/', { name: 'list' })
|
|
43
|
+
@JsonHttpResponse(200)
|
|
44
|
+
async list (event: IncomingHttpEvent): Promise<CommentResponse[]> {
|
|
45
|
+
return await this.commentService.list(event.get<number>('limit', 10))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* List comments by post
|
|
50
|
+
*/
|
|
51
|
+
@Get('/posts/:postId(\\d+)')
|
|
52
|
+
@JsonHttpResponse(200)
|
|
53
|
+
async listByPost (event: IncomingHttpEvent): Promise<CommentResponse[]> {
|
|
54
|
+
return await this.commentService.listByPost(
|
|
55
|
+
event.get<number>('postId', 0),
|
|
56
|
+
event.get<number>('limit', 10)
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* List comments by author
|
|
62
|
+
*/
|
|
63
|
+
@Get('/authors/:authorId(\\d+)')
|
|
64
|
+
@JsonHttpResponse(200)
|
|
65
|
+
async listByAuthor (event: IncomingHttpEvent): Promise<CommentResponse[]> {
|
|
66
|
+
return await this.commentService.listByAuthor(
|
|
67
|
+
event.get<number>('authorId', 0),
|
|
68
|
+
event.get<number>('limit', 10)
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Show a comment by ID
|
|
74
|
+
*/
|
|
75
|
+
@Get('/:comment@id(\\d+)', { bindings: { comment: CommentService } })
|
|
76
|
+
show (event: IncomingHttpEvent): CommentResponse {
|
|
77
|
+
return event.get<CommentResponse>('comment', {} as unknown as CommentResponse)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Create a comment
|
|
82
|
+
*/
|
|
83
|
+
@Post('/posts/:post@id(\\d+)', { bindings: { post: PostService } })
|
|
84
|
+
async create (event: IncomingHttpEvent): Promise<{ id?: number }> {
|
|
85
|
+
const id = await this.commentService.create({
|
|
86
|
+
...event.getBody<CommentModel>({} as any),
|
|
87
|
+
authorId: event.getUser<User>()?.id ?? 0,
|
|
88
|
+
postId: event.get<BlogPost>('post', { id: 0 } as any).id
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return { id: Number(id) }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Delete a comment
|
|
96
|
+
*/
|
|
97
|
+
@Delete('/:id', { rules: { id: /\d+/ } })
|
|
98
|
+
async delete (event: IncomingHttpEvent): Promise<{ statusCode: number }> {
|
|
99
|
+
await this.commentService.delete(event.get<number>('id', 0))
|
|
100
|
+
this.logger.info(`Comment deleted: ${String(event.get<number>('id'))}, by user: ${String(event.getUser<User>()?.id)}`)
|
|
101
|
+
return { statusCode: 204 }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { User } from '../models/User'
|
|
2
|
+
import { ILogger } from '@stone-js/core'
|
|
3
|
+
import { PostService } from '../services/PostService'
|
|
4
|
+
import { PostModel, PostResponse } from '../models/Post'
|
|
5
|
+
import { Delete, EventHandler, Get, Patch, Post } from '@stone-js/router'
|
|
6
|
+
import { IncomingHttpEvent, InternalServerError, JsonHttpResponse } from '@stone-js/http-core'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Post Event Handler Options
|
|
10
|
+
*/
|
|
11
|
+
export interface PostEventHandlerOptions {
|
|
12
|
+
logger: ILogger
|
|
13
|
+
postService: PostService
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Post Event Handler
|
|
18
|
+
*
|
|
19
|
+
* @EventHandler() is a decorator that marks a class as a handler.
|
|
20
|
+
* It acts like a controller in other frameworks.
|
|
21
|
+
*/
|
|
22
|
+
@EventHandler('/posts', { name: 'posts' })
|
|
23
|
+
export class PostEventHandler {
|
|
24
|
+
private readonly logger: ILogger
|
|
25
|
+
private readonly postService: PostService
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create a new instance of PostEventHandler
|
|
29
|
+
*
|
|
30
|
+
* @param postService
|
|
31
|
+
* @param logger
|
|
32
|
+
*/
|
|
33
|
+
constructor ({ postService, logger }: PostEventHandlerOptions) {
|
|
34
|
+
this.logger = logger
|
|
35
|
+
this.postService = postService
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* List all posts
|
|
40
|
+
*/
|
|
41
|
+
@Get('/', { name: 'list' })
|
|
42
|
+
@JsonHttpResponse(200)
|
|
43
|
+
async list (event: IncomingHttpEvent): Promise<PostResponse[]> {
|
|
44
|
+
return await this.postService.list(event.get<number>('limit', 10))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* List all posts by a specific author
|
|
49
|
+
*/
|
|
50
|
+
@Get('/authors/:id(\\d+)', { name: 'listByAuthor' })
|
|
51
|
+
@JsonHttpResponse(200)
|
|
52
|
+
async listByAuthor (event: IncomingHttpEvent): Promise<PostResponse[]> {
|
|
53
|
+
return await this.postService.listByAuthor(
|
|
54
|
+
event.get<number>('id', 0),
|
|
55
|
+
event.get<number>('limit', 10)
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Show a post by ID
|
|
61
|
+
*/
|
|
62
|
+
@Get('/:post@id(\\d+)', { bindings: { post: PostService } })
|
|
63
|
+
show (event: IncomingHttpEvent): PostResponse {
|
|
64
|
+
return event.get<PostResponse>('post', {} as unknown as PostResponse)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Create a post
|
|
69
|
+
*/
|
|
70
|
+
@Post('/')
|
|
71
|
+
async create (event: IncomingHttpEvent): Promise<{ id?: number }> {
|
|
72
|
+
const id = await this.postService.create({
|
|
73
|
+
...event.getBody<PostModel>({} as any),
|
|
74
|
+
authorId: event.getUser<User>()?.id ?? 0
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return { id: Number(id) }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Update a post
|
|
82
|
+
*/
|
|
83
|
+
@Patch('/:id', { rules: { id: /\d+/ } })
|
|
84
|
+
@JsonHttpResponse(204)
|
|
85
|
+
async update (event: IncomingHttpEvent): Promise<void> {
|
|
86
|
+
const updated = await this.postService.update(event.get<number>('id', 0), event.getBody<PostModel>({} as any))
|
|
87
|
+
if (!updated) {
|
|
88
|
+
throw new InternalServerError(`Failed to update post with ID ${String(event.get<number>('id'))}`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Delete a post
|
|
94
|
+
*/
|
|
95
|
+
@Delete('/:id', { rules: { id: /\d+/ } })
|
|
96
|
+
async delete (event: IncomingHttpEvent): Promise<{ statusCode: number }> {
|
|
97
|
+
const deleted = await this.postService.delete(event.get<number>('id', 0))
|
|
98
|
+
if (!deleted) {
|
|
99
|
+
throw new InternalServerError(`Failed to update post with ID ${String(event.get<number>('id'))}`)
|
|
100
|
+
}
|
|
101
|
+
this.logger.info(`Post deleted: ${String(event.get<number>('id'))}, by user: ${String(event.getUser<User>()?.id)}`)
|
|
102
|
+
return { statusCode: 204 }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ILogger } from '@stone-js/core'
|
|
2
|
+
import { EventHandler, Post } from '@stone-js/router'
|
|
3
|
+
import { SecurityService } from '../services/SecurityService'
|
|
4
|
+
import { IncomingHttpEvent, NoContentHttpResponse } from '@stone-js/http-core'
|
|
5
|
+
import { UserChangePassword, UserLogin, UserRegister, UserToken } from '../models/User'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Security Event Handler Options
|
|
9
|
+
*/
|
|
10
|
+
export interface SecurityEventHandlerOptions {
|
|
11
|
+
logger: ILogger
|
|
12
|
+
securityService: SecurityService
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Security Event Handler
|
|
17
|
+
*
|
|
18
|
+
* @EventHandler() is a decorator that marks a class as a handler.
|
|
19
|
+
* @EventHandler() think about it as a controller in other frameworks.
|
|
20
|
+
* Stone.js also provides a @Controller() decorator that is an alias to @EventHandler().
|
|
21
|
+
* If you are familiar with other frameworks, you can use @Controller() instead of @EventHandler().
|
|
22
|
+
*/
|
|
23
|
+
@EventHandler('/', { name: 'security' })
|
|
24
|
+
export class SecurityEventHandler {
|
|
25
|
+
private readonly logger: ILogger
|
|
26
|
+
private readonly securityService: SecurityService
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a new instance of SecurityEventHandler
|
|
30
|
+
*
|
|
31
|
+
* @param securityService
|
|
32
|
+
* @param logger
|
|
33
|
+
*/
|
|
34
|
+
constructor ({ securityService, logger }: SecurityEventHandlerOptions) {
|
|
35
|
+
this.logger = logger
|
|
36
|
+
this.securityService = securityService
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Login a user
|
|
41
|
+
*
|
|
42
|
+
* @param event - IncomingHttpEvent
|
|
43
|
+
* @returns UserToken
|
|
44
|
+
*/
|
|
45
|
+
@Post('/login', { name: 'login' })
|
|
46
|
+
async login (event: IncomingHttpEvent): Promise<UserToken> {
|
|
47
|
+
return await this.securityService.login(
|
|
48
|
+
event,
|
|
49
|
+
event.getBody<UserLogin>({ email: '', password: '' })
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Logout a user
|
|
55
|
+
*
|
|
56
|
+
* @param event - IncomingHttpEvent
|
|
57
|
+
* @returns void
|
|
58
|
+
*/
|
|
59
|
+
@Post('/logout', { name: 'logout' })
|
|
60
|
+
@NoContentHttpResponse({ 'content-type': 'application/json' })
|
|
61
|
+
async logout (event: IncomingHttpEvent): Promise<void> {
|
|
62
|
+
await this.securityService.logout(
|
|
63
|
+
event.get<string>('Authorization', '').replace('Bearer ', '')
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Refresh a token
|
|
69
|
+
*
|
|
70
|
+
* @param event - IncomingHttpEvent
|
|
71
|
+
* @returns UserToken
|
|
72
|
+
*/
|
|
73
|
+
@Post('/refresh', { name: 'refresh' })
|
|
74
|
+
async refresh (event: IncomingHttpEvent): Promise<UserToken> {
|
|
75
|
+
return await this.securityService.refresh(
|
|
76
|
+
event.get<string>('Authorization', '').replace('Bearer ', '')
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Register a user
|
|
82
|
+
*
|
|
83
|
+
* @param event - IncomingHttpEvent
|
|
84
|
+
* @returns UserToken
|
|
85
|
+
*/
|
|
86
|
+
@Post('/register', { name: 'register' })
|
|
87
|
+
@NoContentHttpResponse({ 'content-type': 'application/json' })
|
|
88
|
+
async register (event: IncomingHttpEvent): Promise<void> {
|
|
89
|
+
await this.securityService.register(
|
|
90
|
+
event.getBody<UserRegister>({} as any)
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Change password
|
|
96
|
+
*
|
|
97
|
+
* @param event - IncomingHttpEvent
|
|
98
|
+
* @returns void
|
|
99
|
+
*/
|
|
100
|
+
@Post('/change-password', { name: 'change-password' })
|
|
101
|
+
@NoContentHttpResponse({ 'content-type': 'application/json' })
|
|
102
|
+
async changePassword (event: IncomingHttpEvent): Promise<void> {
|
|
103
|
+
await this.securityService.changePassword(
|
|
104
|
+
event.getUser(),
|
|
105
|
+
event.getBody<UserChangePassword>()
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { ILogger } from '@stone-js/core'
|
|
2
|
+
import { File } from '@stone-js/filesystem'
|
|
3
|
+
import { UserService } from '../services/UserService'
|
|
4
|
+
import { User, UserModel, UserResponse } from '../models/User'
|
|
5
|
+
import { IncomingHttpEvent, JsonHttpResponse } from '@stone-js/http-core'
|
|
6
|
+
import { Delete, EventHandler, Get, Patch, Post } from '@stone-js/router'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* User Event Handler Options
|
|
10
|
+
*/
|
|
11
|
+
export interface UserEventHandlerOptions {
|
|
12
|
+
logger: ILogger
|
|
13
|
+
userService: UserService
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* User Event Handler
|
|
18
|
+
*
|
|
19
|
+
* @EventHandler() is a decorator that marks a class as a handler.
|
|
20
|
+
* @EventHandler() think about it as a controller in other frameworks.
|
|
21
|
+
* Stone.js also provides a @Controller() decorator that is an alias to @EventHandler().
|
|
22
|
+
* If you are familiar with other frameworks, you can use @Controller() instead of @EventHandler().
|
|
23
|
+
*/
|
|
24
|
+
@EventHandler('/users', { name: 'users' })
|
|
25
|
+
export class UserEventHandler {
|
|
26
|
+
private readonly logger: ILogger
|
|
27
|
+
private readonly userService: UserService
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create a new instance of UserEventHandler
|
|
31
|
+
*
|
|
32
|
+
* @param userService
|
|
33
|
+
* @param logger
|
|
34
|
+
*/
|
|
35
|
+
constructor ({ logger, userService }: UserEventHandlerOptions) {
|
|
36
|
+
this.logger = logger
|
|
37
|
+
this.userService = userService
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* List all users
|
|
42
|
+
*
|
|
43
|
+
* With explicit json response type.
|
|
44
|
+
*/
|
|
45
|
+
@Get('/', { name: 'list' })
|
|
46
|
+
@JsonHttpResponse(200)
|
|
47
|
+
async list (event: IncomingHttpEvent): Promise<UserResponse[]> {
|
|
48
|
+
return await this.userService.list(event.get<number>('limit', 10))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Show current user
|
|
53
|
+
*
|
|
54
|
+
* @param event - IncomingHttpEvent
|
|
55
|
+
* @returns User
|
|
56
|
+
*/
|
|
57
|
+
@Get('/me')
|
|
58
|
+
showCurrent (event: IncomingHttpEvent): UserResponse {
|
|
59
|
+
const user = { ...event.getUser<UserModel>(), password: undefined }
|
|
60
|
+
return user as UserResponse
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Show a user
|
|
65
|
+
*
|
|
66
|
+
* With implicit rules definition.
|
|
67
|
+
* Explicit bindings definition for model resolution.
|
|
68
|
+
* Implicit json response type.
|
|
69
|
+
* Because literal object is returned as json.
|
|
70
|
+
*/
|
|
71
|
+
@Get('/:user@id(\\d+)', { bindings: { user: UserService } })
|
|
72
|
+
show (event: IncomingHttpEvent): UserResponse {
|
|
73
|
+
return event.get<UserResponse>('user', {} as unknown as UserResponse)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Show a user avatar
|
|
78
|
+
*
|
|
79
|
+
* @param event - IncomingHttpEvent
|
|
80
|
+
* @returns File
|
|
81
|
+
* @throws FileError if the file is not valid.
|
|
82
|
+
* @throws NotFoundError if the user is not found.
|
|
83
|
+
*/
|
|
84
|
+
@Get('/:user@id(\\d+)/avatar', { bindings: { user: UserService } })
|
|
85
|
+
avatar (event: IncomingHttpEvent): File {
|
|
86
|
+
const user = event.get<UserResponse>('user', {} as unknown as UserResponse)
|
|
87
|
+
return File.create(`public/uploads/${String(user.avatar)}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Create a user
|
|
92
|
+
*
|
|
93
|
+
* With explicit no content json response type.
|
|
94
|
+
* Using headers to define the content type.
|
|
95
|
+
*/
|
|
96
|
+
@Post('/')
|
|
97
|
+
async create (event: IncomingHttpEvent): Promise<{ id?: number }> {
|
|
98
|
+
const id = await this.userService.create(this.handleFileUpload(event))
|
|
99
|
+
return { id: Number(id) }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Update the current user
|
|
104
|
+
*
|
|
105
|
+
* With explicit rules definition.
|
|
106
|
+
*/
|
|
107
|
+
@Patch('/me')
|
|
108
|
+
@JsonHttpResponse(204)
|
|
109
|
+
async updateCurrent (event: IncomingHttpEvent): Promise<UserResponse> {
|
|
110
|
+
return await this.userService.update(
|
|
111
|
+
event.getUser<UserModel>()?.id ?? 0,
|
|
112
|
+
this.handleFileUpload(event)
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Update a user
|
|
118
|
+
*
|
|
119
|
+
* With explicit rules definition.
|
|
120
|
+
*/
|
|
121
|
+
@Patch('/:id', { rules: { id: /\d+/ } })
|
|
122
|
+
@JsonHttpResponse(204)
|
|
123
|
+
async update (event: IncomingHttpEvent): Promise<UserResponse> {
|
|
124
|
+
return await this.userService.update(
|
|
125
|
+
event.get<number>('id', 0),
|
|
126
|
+
this.handleFileUpload(event)
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Delete a user
|
|
132
|
+
*
|
|
133
|
+
* Explcitily returning a status code.
|
|
134
|
+
*/
|
|
135
|
+
@Delete('/:id')
|
|
136
|
+
async delete (event: IncomingHttpEvent): Promise<{ statusCode: number }> {
|
|
137
|
+
await this.userService.delete(event.get<number>('id', 0))
|
|
138
|
+
this.logger.info(`User deleted: ${String(event.get<number>('id'))}, by user: ${String(event.getUser<User>()?.id)}`)
|
|
139
|
+
return { statusCode: 204 }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Handle file upload
|
|
144
|
+
*
|
|
145
|
+
* @param event - IncomingHttpEvent
|
|
146
|
+
* @param payload - UserModel
|
|
147
|
+
*/
|
|
148
|
+
private handleFileUpload (event: IncomingHttpEvent): UserModel {
|
|
149
|
+
const payload = event.getBody<UserModel>({} as any)
|
|
150
|
+
|
|
151
|
+
if (event.hasFile('avatar')) {
|
|
152
|
+
const file = event.getFile('avatar')?.[0]
|
|
153
|
+
payload.avatar = `${crypto.randomUUID()}-${String(file?.getClientOriginalName())}`
|
|
154
|
+
file?.move('public/uploads', payload.avatar)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return payload
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { UserEvent } from '../events/UserEvent'
|
|
2
|
+
import { IEventListener, ILogger, Listener } from '@stone-js/core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* User Event Listener Options
|
|
6
|
+
*/
|
|
7
|
+
export interface UserEventListenerOptions {
|
|
8
|
+
logger: ILogger
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* User event listener
|
|
13
|
+
*/
|
|
14
|
+
@Listener({ event: UserEvent.USER_CREATED })
|
|
15
|
+
export class UserEventListener implements IEventListener<UserEvent> {
|
|
16
|
+
private readonly logger: ILogger
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Create a new instance of UserEventListener
|
|
20
|
+
*
|
|
21
|
+
* @param logger
|
|
22
|
+
*/
|
|
23
|
+
constructor ({ logger }: UserEventListenerOptions) {
|
|
24
|
+
this.logger = logger
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Handle the UserEvent
|
|
29
|
+
*
|
|
30
|
+
* @param event - The event to handle
|
|
31
|
+
*/
|
|
32
|
+
handle (event: UserEvent): void {
|
|
33
|
+
this.logger.info('User event listener', event)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { SecurityService } from '../services/SecurityService'
|
|
2
|
+
import { IMiddleware, Middleware, NextMiddleware } from '@stone-js/core'
|
|
3
|
+
import { IncomingHttpEvent, OutgoingHttpResponse } from '@stone-js/http-core'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Auth middleware Options
|
|
7
|
+
*/
|
|
8
|
+
export interface AuthMiddlewareOptions {
|
|
9
|
+
securityService: SecurityService
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Auth middleware
|
|
14
|
+
*/
|
|
15
|
+
@Middleware({
|
|
16
|
+
global: true,
|
|
17
|
+
params: [['/login', '/register']]
|
|
18
|
+
})
|
|
19
|
+
export class AuthMiddleware implements IMiddleware<IncomingHttpEvent, OutgoingHttpResponse> {
|
|
20
|
+
private readonly securityService: SecurityService
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Create a new instance of AuthMiddleware
|
|
24
|
+
*
|
|
25
|
+
* @param options - The options to create the middleware
|
|
26
|
+
*/
|
|
27
|
+
constructor ({ securityService }: AuthMiddlewareOptions) {
|
|
28
|
+
this.securityService = securityService
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Handle the incoming event
|
|
33
|
+
*
|
|
34
|
+
* @param event - The incoming event
|
|
35
|
+
* @param next - The next middleware
|
|
36
|
+
* @returns The response
|
|
37
|
+
*/
|
|
38
|
+
async handle (
|
|
39
|
+
event: IncomingHttpEvent,
|
|
40
|
+
next: NextMiddleware<IncomingHttpEvent, OutgoingHttpResponse>,
|
|
41
|
+
excludes: string[] = []
|
|
42
|
+
): Promise<OutgoingHttpResponse> {
|
|
43
|
+
const isOptionsRequest = event.isMethod('OPTIONS')
|
|
44
|
+
const isExcludedPath = excludes.includes(event.pathname)
|
|
45
|
+
|
|
46
|
+
if (!isExcludedPath && !isOptionsRequest) {
|
|
47
|
+
const token = event.get<string>('Authorization', '').replace('Bearer ', '')
|
|
48
|
+
const user = await this.securityService.authenticate(token, event.ip, event.userAgent)
|
|
49
|
+
event.setUserResolver(() => user)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return await next(event)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { User } from './User'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Comment Interface
|
|
5
|
+
*/
|
|
6
|
+
export interface CommentModel {
|
|
7
|
+
id: number
|
|
8
|
+
content: string
|
|
9
|
+
postId: number
|
|
10
|
+
authorId: number
|
|
11
|
+
createdAt: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Comment Create Model Interface
|
|
16
|
+
*/
|
|
17
|
+
export interface CommentCreateModel extends Omit<CommentModel, 'id'> {}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Comment Interface
|
|
21
|
+
*/
|
|
22
|
+
export interface Comment extends Omit<CommentModel, 'authorId'> {
|
|
23
|
+
author: User
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Comment Create Request Interface
|
|
28
|
+
* Represents a comment create request resource.
|
|
29
|
+
*/
|
|
30
|
+
export interface CommentCreateRequest {
|
|
31
|
+
content: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Comment Response Interface
|
|
36
|
+
* Represents a comment response resource.
|
|
37
|
+
*/
|
|
38
|
+
export interface CommentResponse extends Comment {}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { User } from './User'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post Model Interface
|
|
5
|
+
*/
|
|
6
|
+
export interface PostModel {
|
|
7
|
+
id: number
|
|
8
|
+
title: string
|
|
9
|
+
content: string
|
|
10
|
+
authorId: number
|
|
11
|
+
createdAt: number
|
|
12
|
+
updatedAt: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Post Create Model Interface
|
|
17
|
+
*/
|
|
18
|
+
export interface PostCreateModel extends Omit<PostModel, 'id'> {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Post Interface
|
|
22
|
+
*/
|
|
23
|
+
export interface Post extends Omit<PostModel, 'authorId'> {
|
|
24
|
+
author: User
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Post Create Request Interface
|
|
29
|
+
* Represents a post create request resource.
|
|
30
|
+
*/
|
|
31
|
+
export interface PostCreateRequest {
|
|
32
|
+
title: string
|
|
33
|
+
content: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Post Update Request Interface
|
|
38
|
+
* Represents a post update request resource.
|
|
39
|
+
*/
|
|
40
|
+
export interface PostUpdateRequest {
|
|
41
|
+
id: number
|
|
42
|
+
title: string
|
|
43
|
+
content: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Post Response Interface
|
|
48
|
+
* Represents a post response resource.
|
|
49
|
+
*/
|
|
50
|
+
export interface PostResponse extends Post {}
|