@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,327 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IncomingHttpEvent,
|
|
3
|
+
OutgoingHttpResponse,
|
|
4
|
+
IncomingHttpEventOptions
|
|
5
|
+
} from '@stone-js/http-core'
|
|
6
|
+
import {
|
|
7
|
+
NodeHttp,
|
|
8
|
+
MetaBodyEventMiddleware,
|
|
9
|
+
MetaFilesEventMiddleware
|
|
10
|
+
} from '@stone-js/node-http-adapter'
|
|
11
|
+
import {
|
|
12
|
+
Hook,
|
|
13
|
+
isEmpty,
|
|
14
|
+
StoneApp,
|
|
15
|
+
LogLevel,
|
|
16
|
+
IContainer,
|
|
17
|
+
IBlueprint,
|
|
18
|
+
AdapterContext,
|
|
19
|
+
BlueprintContext,
|
|
20
|
+
AdapterEventBuilderType,
|
|
21
|
+
AdapterHookListenerContext
|
|
22
|
+
} from '@stone-js/core'
|
|
23
|
+
import { getString } from '@stone-js/env'
|
|
24
|
+
import { Routing } from '@stone-js/router'
|
|
25
|
+
import { NodeConsole } from '@stone-js/node-cli-adapter'
|
|
26
|
+
import { PipelineHookContext } from '@stone-js/pipeline'
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Application
|
|
30
|
+
*
|
|
31
|
+
* This is the main application entry point.
|
|
32
|
+
*
|
|
33
|
+
* @StoneApp() is used to enable the Stone application, it is mandatory.
|
|
34
|
+
* @Routing() is used to enable the routing feature.
|
|
35
|
+
* @NodeHttp() is used to enable the Node HTTP adapter.
|
|
36
|
+
* @NodeConsole() is used to enable the Node Console adapter.
|
|
37
|
+
* @NodeConsole() requires the incoming event type.
|
|
38
|
+
* BodyEventMiddleware is used to parse the incoming event body.
|
|
39
|
+
* BodyEventMiddleware is imported because it is not installed by default.
|
|
40
|
+
*
|
|
41
|
+
* Note: In this example we implement the IBlueprintHook, IAdapterHook and IKernelHook interfaces for demonstration purposes.
|
|
42
|
+
*/
|
|
43
|
+
@Routing()
|
|
44
|
+
@NodeConsole()
|
|
45
|
+
@StoneApp({ name: 'MyApps', logger: { level: LogLevel.INFO } })
|
|
46
|
+
@NodeHttp({ default: true, middleware: [MetaBodyEventMiddleware, MetaFilesEventMiddleware], url: getString('BASE_URL', 'http://localhost:8080') })
|
|
47
|
+
export class Application {
|
|
48
|
+
/**
|
|
49
|
+
* Run before the blueprint is prepared
|
|
50
|
+
*
|
|
51
|
+
* @param context - The blueprint context
|
|
52
|
+
*/
|
|
53
|
+
@Hook('onPreparingBlueprint')
|
|
54
|
+
onPreparingBlueprint ({ blueprint, modules }: BlueprintContext): void {
|
|
55
|
+
blueprint.set('tmpBlueprintTimer', Date.now())
|
|
56
|
+
console.log(`Preparing blueprint by introspecting ${modules.length} modules...`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Run before each blueprint middleware is processed
|
|
61
|
+
*
|
|
62
|
+
* @param context - The pipeline context
|
|
63
|
+
*/
|
|
64
|
+
@Hook('onProcessingBlueprintMiddleware')
|
|
65
|
+
onProcessingBlueprintMiddleware ({ passable, pipe }: PipelineHookContext<BlueprintContext, IBlueprint>): void {
|
|
66
|
+
passable.blueprint.set(`tmpBlueprintMiddleware.${String(pipe.module.name)}`, Date.now())
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Run after each blueprint middleware is processed
|
|
71
|
+
*
|
|
72
|
+
* @param context - The pipeline context
|
|
73
|
+
*/
|
|
74
|
+
@Hook('onBlueprintMiddlewareProcessed')
|
|
75
|
+
onBlueprintMiddlewareProcessed ({ passable, pipe }: PipelineHookContext<BlueprintContext, IBlueprint>): void {
|
|
76
|
+
const name = `tmpBlueprintMiddleware.${String(pipe.module.name)}`
|
|
77
|
+
const start = passable.blueprint.get(name, 0)
|
|
78
|
+
const Type = pipe.isClass !== undefined ? 'Class' : pipe.isFactory !== undefined ? 'Factory' : pipe.isAlias !== undefined ? 'Alias' : 'Callable'
|
|
79
|
+
const value = {
|
|
80
|
+
Middleware: pipe.module.name,
|
|
81
|
+
Type,
|
|
82
|
+
Priority: pipe.priority,
|
|
83
|
+
'Execution Time': `${Date.now() - start}ms`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
passable.blueprint.set(name, value)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Run after the blueprint is prepared
|
|
91
|
+
*
|
|
92
|
+
* @param context - The blueprint context
|
|
93
|
+
*/
|
|
94
|
+
@Hook('onBlueprintPrepared')
|
|
95
|
+
onBlueprintPrepared ({ blueprint }: BlueprintContext): void {
|
|
96
|
+
const timer = Date.now() - blueprint.get('tmpBlueprintTimer', 0)
|
|
97
|
+
const middleware = Object.values(blueprint.get('tmpBlueprintMiddleware', {}))
|
|
98
|
+
const message = `Blueprint prepared in ${timer}ms, with ${middleware.length} middleware`
|
|
99
|
+
|
|
100
|
+
console.table(middleware)
|
|
101
|
+
console.log(message)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Run before the application starts
|
|
106
|
+
*
|
|
107
|
+
* @param context - The adapter context
|
|
108
|
+
*/
|
|
109
|
+
@Hook('onStart')
|
|
110
|
+
onStart ({ blueprint, context }: AdapterHookListenerContext): void {
|
|
111
|
+
console.log('Starting application...')
|
|
112
|
+
console.log('Context isEmpty?', isEmpty(context))
|
|
113
|
+
console.log('Blueprint keys:', Object.keys(blueprint.all()).length)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Run before each adapter middleware is processed
|
|
118
|
+
*
|
|
119
|
+
* @param context - The pipeline context
|
|
120
|
+
*/
|
|
121
|
+
@Hook('onProcessingAdapterMiddleware')
|
|
122
|
+
onProcessingAdapterMiddleware ({ passable, pipe, pipes }: PipelineHookContext<
|
|
123
|
+
AdapterContext<unknown, unknown, unknown, IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse>,
|
|
124
|
+
AdapterEventBuilderType<any>
|
|
125
|
+
>): void {
|
|
126
|
+
console.log('Processing adapter middleware...')
|
|
127
|
+
console.log('Middleware count:', pipes.length)
|
|
128
|
+
console.log('Middleware name:', pipe.name)
|
|
129
|
+
console.log('IncomingEvent isEmpty?', isEmpty(passable.incomingEvent))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Run after each adapter middleware is processed
|
|
134
|
+
*
|
|
135
|
+
* @param context - The pipeline context
|
|
136
|
+
*/
|
|
137
|
+
@Hook('onAdapterMiddlewareProcessed')
|
|
138
|
+
onAdapterMiddlewareProcessed ({ passable, pipe, pipes }: PipelineHookContext<
|
|
139
|
+
AdapterContext<unknown, unknown, unknown, IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse>,
|
|
140
|
+
AdapterEventBuilderType<any>
|
|
141
|
+
>): void {
|
|
142
|
+
console.log('Adapter middleware processed...')
|
|
143
|
+
console.log('Middleware count:', pipes.length)
|
|
144
|
+
console.log('Middleware name:', pipe.name)
|
|
145
|
+
console.log('IncomingEvent isEmpty?', isEmpty(passable.incomingEvent))
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Run before building each incoming event
|
|
150
|
+
*
|
|
151
|
+
* @param context - The adapter context
|
|
152
|
+
*/
|
|
153
|
+
@Hook('onBuildingIncomingEvent')
|
|
154
|
+
onBuildingIncomingEvent ({ context }: AdapterHookListenerContext<
|
|
155
|
+
AdapterContext<unknown, unknown, unknown, IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse>
|
|
156
|
+
>): void {
|
|
157
|
+
console.log('Building incoming event...')
|
|
158
|
+
console.log('IncomingEvent isEmpty?', isEmpty(context?.incomingEvent))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Run before handling each adapter error
|
|
163
|
+
*
|
|
164
|
+
* @param context - The adapter context
|
|
165
|
+
*/
|
|
166
|
+
@Hook('onHandlingAdapterError')
|
|
167
|
+
onHandlingAdapterError ({ error }: AdapterHookListenerContext<
|
|
168
|
+
AdapterContext<unknown, unknown, unknown, IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse>
|
|
169
|
+
>): void {
|
|
170
|
+
console.error('Handling adapter error...')
|
|
171
|
+
console.error('Error:', error)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Run before building each outgoing response
|
|
176
|
+
*
|
|
177
|
+
* @param context - The adapter context
|
|
178
|
+
*/
|
|
179
|
+
@Hook('onBuildingRawResponse')
|
|
180
|
+
onBuildingRawResponse ({ context }: AdapterHookListenerContext<
|
|
181
|
+
AdapterContext<unknown, unknown, unknown, IncomingHttpEvent, IncomingHttpEventOptions, OutgoingHttpResponse>
|
|
182
|
+
>): void {
|
|
183
|
+
console.log('Building raw response...')
|
|
184
|
+
console.log('IncomingEvent isEmpty?', isEmpty(context?.incomingEvent))
|
|
185
|
+
console.log('OutgoingResponse isEmpty?', isEmpty(context?.outgoingResponse))
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Run just before the application stops
|
|
190
|
+
*
|
|
191
|
+
* @param context - The adapter context
|
|
192
|
+
*/
|
|
193
|
+
@Hook('onStop')
|
|
194
|
+
onStop ({ blueprint, context }: AdapterHookListenerContext): void {
|
|
195
|
+
console.log('Stopping application...')
|
|
196
|
+
console.log('Context isEmpty?', isEmpty(context))
|
|
197
|
+
console.log('Blueprint keys:', Object.keys(blueprint.all()).length)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Run after the application is initialized
|
|
202
|
+
* The container is available at this point.
|
|
203
|
+
* All services are registered and ready to be used.
|
|
204
|
+
*
|
|
205
|
+
* @param container - The container
|
|
206
|
+
*/
|
|
207
|
+
@Hook('onInit')
|
|
208
|
+
onInit (container: IContainer): void {
|
|
209
|
+
console.log('Initializing application...')
|
|
210
|
+
console.log('Container services count:', container.getBindings().size)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Run before handling each event
|
|
215
|
+
*
|
|
216
|
+
* @param container - The container
|
|
217
|
+
*/
|
|
218
|
+
@Hook('onHandlingEvent')
|
|
219
|
+
onHandlingEvent (container: IContainer): void {
|
|
220
|
+
try {
|
|
221
|
+
console.log('Handling event...')
|
|
222
|
+
container.make('event')
|
|
223
|
+
} catch (error: any) {
|
|
224
|
+
console.log('The incoming event is not yet bound at this stage', error.message)
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Run before processing each kernel middleware
|
|
230
|
+
*
|
|
231
|
+
* @param context - The pipeline context
|
|
232
|
+
*/
|
|
233
|
+
@Hook('onProcessingKernelMiddleware')
|
|
234
|
+
onProcessingKernelMiddleware (
|
|
235
|
+
{ passable, pipe, pipes }: PipelineHookContext<IncomingHttpEvent, OutgoingHttpResponse>
|
|
236
|
+
): void {
|
|
237
|
+
console.log('Processing kernel middleware...')
|
|
238
|
+
console.log('Middleware count:', pipes.length)
|
|
239
|
+
console.log('Middleware name:', pipe.name)
|
|
240
|
+
console.log('Incoming Source name', passable.source.platform)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Run after processing each kernel middleware
|
|
245
|
+
*
|
|
246
|
+
* @param context - The pipeline context
|
|
247
|
+
*/
|
|
248
|
+
@Hook('onKernelMiddlewareProcessed')
|
|
249
|
+
onKernelMiddlewareProcessed (
|
|
250
|
+
{ passable, pipe, pipes }: PipelineHookContext<IncomingHttpEvent, OutgoingHttpResponse>
|
|
251
|
+
): void {
|
|
252
|
+
console.log('Kernel middleware processed...')
|
|
253
|
+
console.log('Middleware count:', pipes.length)
|
|
254
|
+
console.log('Middleware name:', pipe.name)
|
|
255
|
+
console.log('Incoming Source name', passable.source.platform)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Run before executing each event handler
|
|
260
|
+
*
|
|
261
|
+
* @param container - The container
|
|
262
|
+
*/
|
|
263
|
+
@Hook('onExecutingEventHandler')
|
|
264
|
+
onExecutingEventHandler ({ event }: { event: IncomingHttpEvent }): void {
|
|
265
|
+
console.log('Executing event handler...')
|
|
266
|
+
console.log('The incoming event is yet bound at this stage', event.source.platform)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Run before handling each error
|
|
271
|
+
*
|
|
272
|
+
* @param container - The container
|
|
273
|
+
*/
|
|
274
|
+
@Hook('onExecutingErrorHandler')
|
|
275
|
+
onExecutingErrorHandler ({ error }: { error: any }): void {
|
|
276
|
+
console.log('Executing error handler...')
|
|
277
|
+
console.log('Error', error)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Run before preparing each response
|
|
282
|
+
*
|
|
283
|
+
* @param container - The container
|
|
284
|
+
*/
|
|
285
|
+
@Hook('onPreparingResponse')
|
|
286
|
+
onPreparingResponse ({ response }: { response: OutgoingHttpResponse }): void {
|
|
287
|
+
console.log('Preparing response...')
|
|
288
|
+
console.log('Response headers', response.headers)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Run after preparing each response
|
|
293
|
+
*
|
|
294
|
+
* @param container - The container
|
|
295
|
+
*/
|
|
296
|
+
@Hook('onResponsePrepared')
|
|
297
|
+
onResponsePrepared ({ response }: { response: OutgoingHttpResponse }): void {
|
|
298
|
+
console.log('Response prepared...')
|
|
299
|
+
console.log('Response headers', response.headers)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Run after handling each event
|
|
304
|
+
*
|
|
305
|
+
* @param context - The pipeline context
|
|
306
|
+
*/
|
|
307
|
+
@Hook('onEventHandled')
|
|
308
|
+
onEventHandled (
|
|
309
|
+
{ event, response }: { event: IncomingHttpEvent, response: OutgoingHttpResponse }
|
|
310
|
+
): void {
|
|
311
|
+
console.log('Event handled...')
|
|
312
|
+
console.log('Event headers', event.headers)
|
|
313
|
+
console.log('Response headers', response.headers)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Run after executing each event handler
|
|
318
|
+
*
|
|
319
|
+
* @param container - The container
|
|
320
|
+
*/
|
|
321
|
+
@Hook('onTerminate')
|
|
322
|
+
onTerminate (container: IContainer): void {
|
|
323
|
+
console.log('Terminating event handling...')
|
|
324
|
+
console.log('Is IncomingEvent exist', container.bound('event'))
|
|
325
|
+
console.log('Is OutgoingResponse exist', container.bound('response'))
|
|
326
|
+
}
|
|
327
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { UserService } from '../services/UserService'
|
|
2
|
+
import { SessionService } from '../services/SessionService'
|
|
3
|
+
import { ILogger, IncomingEvent, isEmpty } from '@stone-js/core'
|
|
4
|
+
import { Command, CommandBuilder, ICommandHandler } from '@stone-js/node-cli-adapter'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ListSessionsCommandOptions
|
|
8
|
+
*/
|
|
9
|
+
export interface ListSessionsCommandOptions {
|
|
10
|
+
logger: ILogger
|
|
11
|
+
userService: UserService
|
|
12
|
+
sessionService: SessionService
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* List sessions command
|
|
17
|
+
*/
|
|
18
|
+
@Command({
|
|
19
|
+
alias: 'ls',
|
|
20
|
+
name: 'list-sessions',
|
|
21
|
+
desc: 'List sessions',
|
|
22
|
+
options: (yargs: CommandBuilder) => {
|
|
23
|
+
return yargs
|
|
24
|
+
.option('email', {
|
|
25
|
+
alias: 'e',
|
|
26
|
+
type: 'string',
|
|
27
|
+
default: undefined,
|
|
28
|
+
desc: 'Filter sessions by email'
|
|
29
|
+
})
|
|
30
|
+
.option('limit', {
|
|
31
|
+
alias: 'l',
|
|
32
|
+
type: 'number',
|
|
33
|
+
default: false,
|
|
34
|
+
desc: 'Number of sessions to list'
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
export class ListSessionsCommand implements ICommandHandler<IncomingEvent> {
|
|
39
|
+
private readonly logger: ILogger
|
|
40
|
+
private readonly userService: UserService
|
|
41
|
+
private readonly sessionService: SessionService
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a new instance of ListSessionsCommand
|
|
45
|
+
*
|
|
46
|
+
* @param logger
|
|
47
|
+
* @param sessionService
|
|
48
|
+
*/
|
|
49
|
+
constructor ({ logger, sessionService, userService }: ListSessionsCommandOptions) {
|
|
50
|
+
this.logger = logger
|
|
51
|
+
this.userService = userService
|
|
52
|
+
this.sessionService = sessionService
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Handler for the ListSessionsCommand
|
|
57
|
+
*
|
|
58
|
+
* @param event - Incoming event
|
|
59
|
+
*/
|
|
60
|
+
async handle (event: IncomingEvent): Promise<void> {
|
|
61
|
+
const email = event.get<number>('email')
|
|
62
|
+
const limit = event.get<number>('limit', 10)
|
|
63
|
+
const user = isEmpty(email) ? undefined : await this.userService.findByEmail({ email })
|
|
64
|
+
const sessions = isEmpty(user)
|
|
65
|
+
? await this.sessionService.list(limit)
|
|
66
|
+
: await this.sessionService.getByUser(user, limit)
|
|
67
|
+
this.logger.info('List sessions command')
|
|
68
|
+
console.table(sessions)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { UserService } from '../services/UserService'
|
|
2
|
+
import { ILogger, IncomingEvent } from '@stone-js/core'
|
|
3
|
+
import { Command, CommandBuilder, ICommandHandler } from '@stone-js/node-cli-adapter'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* ListUsersCommandOptions
|
|
7
|
+
*/
|
|
8
|
+
export interface ListUsersCommandOptions {
|
|
9
|
+
logger: ILogger
|
|
10
|
+
userService: UserService
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List users command
|
|
15
|
+
*/
|
|
16
|
+
@Command({
|
|
17
|
+
alias: 'lu',
|
|
18
|
+
name: 'list-users',
|
|
19
|
+
desc: 'List users',
|
|
20
|
+
options: (yargs: CommandBuilder) => {
|
|
21
|
+
return yargs
|
|
22
|
+
.option('limit', {
|
|
23
|
+
alias: 'l',
|
|
24
|
+
type: 'number',
|
|
25
|
+
default: false,
|
|
26
|
+
desc: 'Number of users to list'
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
export class ListUsersCommand implements ICommandHandler<IncomingEvent> {
|
|
31
|
+
private readonly logger: ILogger
|
|
32
|
+
private readonly userService: UserService
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Create a new instance of ListUsersCommand
|
|
36
|
+
*
|
|
37
|
+
* @param logger
|
|
38
|
+
* @param userService
|
|
39
|
+
*/
|
|
40
|
+
constructor ({ logger, userService }: ListUsersCommandOptions) {
|
|
41
|
+
this.logger = logger
|
|
42
|
+
this.userService = userService
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Handler for the ListUsersCommand
|
|
47
|
+
*
|
|
48
|
+
* @param event - Incoming event
|
|
49
|
+
*/
|
|
50
|
+
async handle (event: IncomingEvent): Promise<void> {
|
|
51
|
+
const limit = event.get<number>('limit', 10)
|
|
52
|
+
const users = await this.userService.list(limit)
|
|
53
|
+
this.logger.info('List users command')
|
|
54
|
+
console.table(users)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Config } from '@libsql/client'
|
|
2
|
+
import { getString } from '@stone-js/env'
|
|
3
|
+
import { CORSHeadersMiddleware } from '@stone-js/http-core'
|
|
4
|
+
import { Configuration, defineBlueprintMiddleware, IBlueprint, IConfiguration, LogLevel, Promiseable } from '@stone-js/core'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* User Implicit Configuration
|
|
8
|
+
*
|
|
9
|
+
* Explicit configuration takes precedence over implicit configuration.
|
|
10
|
+
* Implicit configuration are defined at decorators level.
|
|
11
|
+
*/
|
|
12
|
+
@Configuration()
|
|
13
|
+
export class AppConfiguration implements IConfiguration {
|
|
14
|
+
/**
|
|
15
|
+
* Configure the application
|
|
16
|
+
*
|
|
17
|
+
* @param blueprint - The blueprint to configure
|
|
18
|
+
*/
|
|
19
|
+
configure (blueprint: IBlueprint): Promiseable<void> {
|
|
20
|
+
blueprint
|
|
21
|
+
.set('database', this.databaseConfig())
|
|
22
|
+
.set('security', this.securityConfig())
|
|
23
|
+
.set('stone.logger.level', LogLevel.INFO)
|
|
24
|
+
.set('stone.http.cors.preflightStop', true)
|
|
25
|
+
.set('stone.http.cors.allowedHeaders', ['*'])
|
|
26
|
+
.set(defineBlueprintMiddleware(CORSHeadersMiddleware))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the database configuration
|
|
31
|
+
*/
|
|
32
|
+
private databaseConfig (): Config {
|
|
33
|
+
return {
|
|
34
|
+
url: getString('DATABASE_URL', 'file:local.db')
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the security configuration
|
|
40
|
+
*/
|
|
41
|
+
private securityConfig (): Record<string, any> {
|
|
42
|
+
return {
|
|
43
|
+
jwt: {
|
|
44
|
+
expiresIn: 3600
|
|
45
|
+
},
|
|
46
|
+
secret: getString('SECURITY_JWT_SECRET', 'non_prod_secret'),
|
|
47
|
+
bcrypt: {
|
|
48
|
+
saltRounds: 10
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Configuration, IBlueprint, IConfiguration } from '@stone-js/core'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* User Live Configuration
|
|
5
|
+
* Usefull for loading configuration without restarting the application.
|
|
6
|
+
* Live explicit configuration takes precedence over explicit and implicit configurations.
|
|
7
|
+
* Note: Only applicable for server applications.
|
|
8
|
+
*/
|
|
9
|
+
@Configuration({ live: true })
|
|
10
|
+
export class UserLiveConfiguration implements IConfiguration {
|
|
11
|
+
/**
|
|
12
|
+
* Configure the application
|
|
13
|
+
*
|
|
14
|
+
* @param blueprint - The blueprint to configure
|
|
15
|
+
*/
|
|
16
|
+
async configure (blueprint: IBlueprint): Promise<void> {
|
|
17
|
+
blueprint.set('stone.name', await this.fetchConfigurationRemotely())
|
|
18
|
+
console.log('I am live cause i am loaded at each request...')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fetch the configuration remotely
|
|
23
|
+
*/
|
|
24
|
+
async fetchConfigurationRemotely (): Promise<string> {
|
|
25
|
+
console.log('Fetching configuration...')
|
|
26
|
+
return await Promise.resolve('My Fetched app name')
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Client, Config, createClient } from '@libsql/client'
|
|
2
|
+
|
|
3
|
+
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DatabaseClient
|
|
7
|
+
*/
|
|
8
|
+
export class DatabaseClient {
|
|
9
|
+
private static _client?: Client
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The client instance
|
|
13
|
+
*/
|
|
14
|
+
static get client (): Client {
|
|
15
|
+
if (this._client === undefined) {
|
|
16
|
+
throw new Error('Database client is not initialized.')
|
|
17
|
+
}
|
|
18
|
+
return this._client
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a new client instance
|
|
23
|
+
*
|
|
24
|
+
* @param config - The configuration object for the client
|
|
25
|
+
* @returns The client instance
|
|
26
|
+
*/
|
|
27
|
+
static create (config: Config): Client {
|
|
28
|
+
if (this._client === undefined) {
|
|
29
|
+
this._client = createClient(config)
|
|
30
|
+
}
|
|
31
|
+
return this._client
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Close the client instance
|
|
36
|
+
*/
|
|
37
|
+
static close (): void {
|
|
38
|
+
if (this._client !== undefined) {
|
|
39
|
+
this._client.close()
|
|
40
|
+
this._client = undefined
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core'
|
|
2
|
+
|
|
3
|
+
// User Table
|
|
4
|
+
export const users = sqliteTable('users', {
|
|
5
|
+
id: integer('id').primaryKey(),
|
|
6
|
+
name: text('name').notNull(),
|
|
7
|
+
password: text('password'),
|
|
8
|
+
avatar: text('avatar'),
|
|
9
|
+
email: text('email').unique().notNull(),
|
|
10
|
+
updatedAt: integer('updated_at').notNull(),
|
|
11
|
+
createdAt: integer('created_at').notNull() // Store timestamps as integers (Unix timestamp)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export const sessions = sqliteTable('sessions', {
|
|
15
|
+
id: integer('id').primaryKey(),
|
|
16
|
+
ip: text('ip').notNull(),
|
|
17
|
+
userAgent: text('user_agent'),
|
|
18
|
+
closedAt: integer('closed_at'),
|
|
19
|
+
uuid: text('uuid').unique().notNull(),
|
|
20
|
+
createdAt: integer('created_at').notNull(),
|
|
21
|
+
expiresAt: integer('expires_at').notNull(),
|
|
22
|
+
lastActivityAt: integer('last_activity_at').notNull(),
|
|
23
|
+
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'cascade' })
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
// Post Table
|
|
27
|
+
export const posts = sqliteTable('posts', {
|
|
28
|
+
id: integer('id').primaryKey(),
|
|
29
|
+
title: text('title').notNull(),
|
|
30
|
+
content: text('content').notNull(),
|
|
31
|
+
createdAt: integer('created_at').notNull(),
|
|
32
|
+
updatedAt: integer('updated_at').notNull(),
|
|
33
|
+
authorId: integer('author_id').notNull().references(() => users.id, { onDelete: 'cascade' })
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
// Comment Table
|
|
37
|
+
export const comments = sqliteTable('comments', {
|
|
38
|
+
id: integer('id').primaryKey(),
|
|
39
|
+
content: text('content').notNull(),
|
|
40
|
+
createdAt: integer('created_at').notNull(),
|
|
41
|
+
authorId: integer('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
42
|
+
postId: integer('post_id').notNull().references(() => posts.id, { onDelete: 'cascade' })
|
|
43
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BadCredentialsError } from '../errors/CredentialsError'
|
|
2
|
+
import { ErrorHandler, IErrorHandler, ILogger, Promiseable } from '@stone-js/core'
|
|
3
|
+
import { BadRequestError, HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR, HTTP_NOT_FOUND, HTTP_UNAUTHORIZED, IncomingHttpEvent, NotFoundError, UnauthorizedError } from '@stone-js/http-core'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* User Error Handler Options
|
|
7
|
+
*/
|
|
8
|
+
export interface SecurityErrorHandlerOptions {
|
|
9
|
+
logger: ILogger
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* User Error Handler
|
|
14
|
+
*/
|
|
15
|
+
@ErrorHandler({ error: ['BadCredentialsError', 'UnauthorizedError', 'NotFoundError', 'BadRequestError'] })
|
|
16
|
+
export class SecurityErrorHandler implements IErrorHandler<IncomingHttpEvent> {
|
|
17
|
+
private readonly logger: ILogger
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create a new instance of SecurityErrorHandler
|
|
21
|
+
*
|
|
22
|
+
* @param logger
|
|
23
|
+
*/
|
|
24
|
+
constructor ({ logger }: SecurityErrorHandlerOptions) {
|
|
25
|
+
this.logger = logger
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Handle CredentialsError and UnauthorizedError
|
|
30
|
+
*
|
|
31
|
+
* @param error - The error to handle
|
|
32
|
+
* @param _event - The incoming event
|
|
33
|
+
* @returns The response
|
|
34
|
+
*/
|
|
35
|
+
handle (error: BadCredentialsError | UnauthorizedError | NotFoundError | BadRequestError, _event: IncomingHttpEvent): Promiseable<unknown> {
|
|
36
|
+
this.logger.error(error.message)
|
|
37
|
+
let message: string = 'An error occurred'
|
|
38
|
+
let statusCode: number = HTTP_INTERNAL_SERVER_ERROR
|
|
39
|
+
|
|
40
|
+
if (error instanceof NotFoundError) {
|
|
41
|
+
message = error.message
|
|
42
|
+
statusCode = HTTP_NOT_FOUND
|
|
43
|
+
} else if (error instanceof BadCredentialsError) {
|
|
44
|
+
message = 'Invalid credentials'
|
|
45
|
+
statusCode = HTTP_UNAUTHORIZED
|
|
46
|
+
} else if (error instanceof UnauthorizedError) {
|
|
47
|
+
statusCode = HTTP_UNAUTHORIZED
|
|
48
|
+
message = 'You are not authorized to perform this action'
|
|
49
|
+
} else if (error instanceof BadRequestError) {
|
|
50
|
+
statusCode = HTTP_BAD_REQUEST
|
|
51
|
+
message = error.message
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
statusCode,
|
|
56
|
+
content: {
|
|
57
|
+
errors: { message }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ErrorOptions } from '@stone-js/core'
|
|
2
|
+
import { UnauthorizedError } from '@stone-js/http-core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bad Credentials Error
|
|
6
|
+
*/
|
|
7
|
+
export class BadCredentialsError extends UnauthorizedError {
|
|
8
|
+
constructor (message: string, options?: ErrorOptions) {
|
|
9
|
+
super(message, options)
|
|
10
|
+
this.name = 'BadCredentialsError'
|
|
11
|
+
}
|
|
12
|
+
}
|