@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,77 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken'
|
|
2
|
+
import { Session } from './Session'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* User Interface
|
|
6
|
+
*/
|
|
7
|
+
export interface UserModel {
|
|
8
|
+
id: number
|
|
9
|
+
name: string
|
|
10
|
+
email: string
|
|
11
|
+
avatar?: string | null
|
|
12
|
+
password?: string | null
|
|
13
|
+
createdAt: number
|
|
14
|
+
updatedAt: number
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* User Interface
|
|
19
|
+
*/
|
|
20
|
+
export interface User extends Omit<UserModel, 'password'> {}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* User Response Interface
|
|
24
|
+
* Represents a user response resource.
|
|
25
|
+
*/
|
|
26
|
+
export interface UserResponse extends User {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* User Request Interface
|
|
30
|
+
* Represents a user request resource.
|
|
31
|
+
*/
|
|
32
|
+
export interface UserRequest {
|
|
33
|
+
name: string
|
|
34
|
+
email: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* User Login Interface
|
|
39
|
+
*/
|
|
40
|
+
export interface UserLogin {
|
|
41
|
+
email: string
|
|
42
|
+
password: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* User Register Interface
|
|
47
|
+
*/
|
|
48
|
+
export interface UserRegister {
|
|
49
|
+
name: string
|
|
50
|
+
email: string
|
|
51
|
+
password: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* User Change Password Interface
|
|
56
|
+
*/
|
|
57
|
+
export interface UserChangePassword {
|
|
58
|
+
password: string
|
|
59
|
+
newPassword: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* User Token Interface
|
|
64
|
+
*/
|
|
65
|
+
export interface UserToken {
|
|
66
|
+
expiresIn: number
|
|
67
|
+
tokenType: string
|
|
68
|
+
accessToken: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* User Token Payload Interface
|
|
73
|
+
*/
|
|
74
|
+
export interface UserTokenPayload extends jwt.JwtPayload {
|
|
75
|
+
user: User
|
|
76
|
+
session: Session
|
|
77
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Hook,
|
|
3
|
+
Provider,
|
|
4
|
+
IContainer,
|
|
5
|
+
IServiceProvider,
|
|
6
|
+
AdapterHookListenerContext
|
|
7
|
+
} from '@stone-js/core'
|
|
8
|
+
import { Config } from '@libsql/client'
|
|
9
|
+
import { drizzle } from 'drizzle-orm/libsql'
|
|
10
|
+
import { DatabaseClient } from '../database/DatabaseClient'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Drizzle Service Provider
|
|
14
|
+
*
|
|
15
|
+
* In this example, we are using both ServiceProvider to bind the drizzle instance to the container
|
|
16
|
+
* And AdapterHook to start and stop the drizzle client
|
|
17
|
+
*/
|
|
18
|
+
@Provider()
|
|
19
|
+
export class DrizzleServiceProvider implements IServiceProvider {
|
|
20
|
+
/**
|
|
21
|
+
* Create a new instance of DrizzleServiceProvider
|
|
22
|
+
*
|
|
23
|
+
* @param options
|
|
24
|
+
*/
|
|
25
|
+
constructor (private readonly container: IContainer) {}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* On start hook that will be called
|
|
29
|
+
* once when the application starts
|
|
30
|
+
*
|
|
31
|
+
* @param context - The adapter hook listener context
|
|
32
|
+
*/
|
|
33
|
+
@Hook('onStart')
|
|
34
|
+
onStart ({ blueprint }: AdapterHookListenerContext): void {
|
|
35
|
+
DatabaseClient.create(
|
|
36
|
+
blueprint.get<Config>('database', { url: 'file:local.db' })
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Register services to the container
|
|
42
|
+
*/
|
|
43
|
+
register (): void {
|
|
44
|
+
this.container
|
|
45
|
+
.instanceIf('drizzle', drizzle(DatabaseClient.client))
|
|
46
|
+
.alias('drizzle', ['db', 'database'])
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* On stop hook that will be called
|
|
51
|
+
* once when the application stops
|
|
52
|
+
*
|
|
53
|
+
* @param context - The adapter hook listener context
|
|
54
|
+
*/
|
|
55
|
+
@Hook('onStop')
|
|
56
|
+
onStop (): void {
|
|
57
|
+
DatabaseClient.close()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { desc, eq } from 'drizzle-orm'
|
|
2
|
+
import { isNotEmpty, Stone } from '@stone-js/core'
|
|
3
|
+
import { LibSQLDatabase } from 'drizzle-orm/libsql'
|
|
4
|
+
import { comments, users } from '../database/schema'
|
|
5
|
+
import { Comment, CommentCreateModel, CommentModel } from '../models/Comment'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Comment Repository Options
|
|
9
|
+
*/
|
|
10
|
+
export interface CommentRepositoryOptions {
|
|
11
|
+
database: LibSQLDatabase
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Comment Repository
|
|
16
|
+
*
|
|
17
|
+
* Manages comment-related database operations.
|
|
18
|
+
*/
|
|
19
|
+
@Stone({ alias: 'commentRepository' })
|
|
20
|
+
export class CommentRepository {
|
|
21
|
+
private readonly database: LibSQLDatabase
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a new instance of CommentRepository.
|
|
25
|
+
*
|
|
26
|
+
* @param options - The options to create the repository.
|
|
27
|
+
*/
|
|
28
|
+
constructor ({ database }: CommentRepositoryOptions) {
|
|
29
|
+
this.database = database
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves a list of comments with optional filtering and sorting.
|
|
34
|
+
*
|
|
35
|
+
* @param options - Optional filters (postId, authorId, limit, orderBy).
|
|
36
|
+
* @returns The list of comments.
|
|
37
|
+
*/
|
|
38
|
+
async list (options?: { postId?: number, authorId?: number, limit?: number }): Promise<Comment[]> {
|
|
39
|
+
const query = this
|
|
40
|
+
.database
|
|
41
|
+
.select(this.selectWithAuthor())
|
|
42
|
+
.from(comments)
|
|
43
|
+
.innerJoin(users, eq(comments.authorId, users.id))
|
|
44
|
+
|
|
45
|
+
if (options?.postId !== undefined) {
|
|
46
|
+
await query.where(eq(comments.postId, options.postId))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (options?.authorId !== undefined) {
|
|
50
|
+
await query.where(eq(comments.authorId, options.authorId))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
await query.orderBy(desc(comments.createdAt))
|
|
54
|
+
|
|
55
|
+
if (options?.limit !== undefined) {
|
|
56
|
+
await query.limit(options.limit)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return await query.all() as Comment[]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Retrieves all comments created by a specific user.
|
|
64
|
+
*
|
|
65
|
+
* @param authorId - The ID of the user whose comments are being retrieved.
|
|
66
|
+
* @param limit - The number of comments to retrieve.
|
|
67
|
+
* @returns The list of comments.
|
|
68
|
+
*/
|
|
69
|
+
async listByAuthor (authorId: number, limit: number): Promise<Comment[]> {
|
|
70
|
+
return await this.list({ authorId, limit })
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Retrieves all comments for a specific post.
|
|
75
|
+
*
|
|
76
|
+
* @param postId - The ID of the post whose comments are being retrieved.
|
|
77
|
+
* @param limit - The number of comments to retrieve.
|
|
78
|
+
* @returns The list of comments.
|
|
79
|
+
*/
|
|
80
|
+
async listByPost (postId: number, limit: number): Promise<Comment[]> {
|
|
81
|
+
return await this.list({ postId, limit })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Finds a comment by its ID.
|
|
86
|
+
*
|
|
87
|
+
* @param commentId - The ID of the comment to retrieve.
|
|
88
|
+
* @returns The comment or `undefined` if not found.
|
|
89
|
+
*/
|
|
90
|
+
async findById (commentId: number): Promise<Comment | undefined> {
|
|
91
|
+
return await this.database
|
|
92
|
+
.select(this.selectWithAuthor())
|
|
93
|
+
.from(comments)
|
|
94
|
+
.innerJoin(users, eq(comments.authorId, users.id))
|
|
95
|
+
.where(eq(comments.id, commentId))
|
|
96
|
+
.get() as Comment | undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Creates a new comment.
|
|
101
|
+
*
|
|
102
|
+
* @param comment - The comment to create.
|
|
103
|
+
* @returns The ID of the created comment.
|
|
104
|
+
*/
|
|
105
|
+
async create (comment: CommentCreateModel): Promise<bigint | undefined> {
|
|
106
|
+
const result = await this.database.insert(comments).values(comment)
|
|
107
|
+
return result.lastInsertRowid
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Updates a comment by its ID.
|
|
112
|
+
*
|
|
113
|
+
* @param commentId - The ID of the comment to update.
|
|
114
|
+
* @param comment - The updated comment data.
|
|
115
|
+
* @returns The updated comment or `undefined` if not found.
|
|
116
|
+
*/
|
|
117
|
+
async update (commentId: number, comment: Partial<CommentModel>): Promise<Comment | undefined> {
|
|
118
|
+
return await this.database
|
|
119
|
+
.update(comments)
|
|
120
|
+
.set(comment)
|
|
121
|
+
.where(eq(comments.id, commentId))
|
|
122
|
+
.returning(this.selectWithAuthor())
|
|
123
|
+
.get() as Comment | undefined
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Deletes a comment by its ID.
|
|
128
|
+
*
|
|
129
|
+
* @param commentId - The ID of the comment to delete.
|
|
130
|
+
* @returns `true` if the comment was deleted, otherwise `false`.
|
|
131
|
+
*/
|
|
132
|
+
async delete (commentId: number): Promise<boolean> {
|
|
133
|
+
const result = await this.database.delete(comments).where(eq(comments.id, commentId)).run()
|
|
134
|
+
return isNotEmpty<bigint>(result.lastInsertRowid) && result.lastInsertRowid > 0
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Selects comments with author and post information.
|
|
139
|
+
*/
|
|
140
|
+
private selectWithAuthor (): Record<string, any> {
|
|
141
|
+
return {
|
|
142
|
+
id: comments.id,
|
|
143
|
+
postId: comments.postId,
|
|
144
|
+
content: comments.content,
|
|
145
|
+
createdAt: comments.createdAt,
|
|
146
|
+
author: {
|
|
147
|
+
id: users.id,
|
|
148
|
+
name: users.name,
|
|
149
|
+
email: users.email,
|
|
150
|
+
createdAt: users.createdAt,
|
|
151
|
+
updatedAt: users.updatedAt
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { desc, eq } from 'drizzle-orm'
|
|
2
|
+
import { posts, users } from '../database/schema'
|
|
3
|
+
import { isNotEmpty, Stone } from '@stone-js/core'
|
|
4
|
+
import { LibSQLDatabase } from 'drizzle-orm/libsql'
|
|
5
|
+
import { Post, PostCreateModel, PostModel } from '../models/Post'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Post Repository Options
|
|
9
|
+
*/
|
|
10
|
+
export interface PostRepositoryOptions {
|
|
11
|
+
database: LibSQLDatabase
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Post Repository
|
|
16
|
+
*
|
|
17
|
+
* Manages post-related database operations.
|
|
18
|
+
*/
|
|
19
|
+
@Stone({ alias: 'postRepository' })
|
|
20
|
+
export class PostRepository {
|
|
21
|
+
private readonly database: LibSQLDatabase
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a new instance of PostRepository
|
|
25
|
+
*
|
|
26
|
+
* @param options - The options to create the repository
|
|
27
|
+
*/
|
|
28
|
+
constructor ({ database }: PostRepositoryOptions) {
|
|
29
|
+
this.database = database
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves a list of posts with optional filtering and sorting.
|
|
34
|
+
*
|
|
35
|
+
* @param options - Optional filters (authorId, limit, orderBy).
|
|
36
|
+
* @returns The list of posts.
|
|
37
|
+
*/
|
|
38
|
+
async list (options?: { authorId?: number, limit?: number }): Promise<Post[]> {
|
|
39
|
+
const query = this
|
|
40
|
+
.database
|
|
41
|
+
.select(this.selectWithAuthor())
|
|
42
|
+
.from(posts)
|
|
43
|
+
.innerJoin(users, eq(posts.authorId, users.id))
|
|
44
|
+
|
|
45
|
+
if (options?.authorId !== undefined) {
|
|
46
|
+
await query.where(eq(posts.authorId, options.authorId))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await query.orderBy(desc(posts.createdAt))
|
|
50
|
+
|
|
51
|
+
if (options?.limit !== undefined) {
|
|
52
|
+
await query.limit(options.limit)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return await query.all() as Post[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Retrieves all posts created by a specific user.
|
|
60
|
+
*
|
|
61
|
+
* @param user - The user whose posts are being retrieved.
|
|
62
|
+
* @param limit - The number of posts to retrieve.
|
|
63
|
+
* @returns The list of posts.
|
|
64
|
+
*/
|
|
65
|
+
async listByAuthor (authorId: number, limit: number): Promise<Post[]> {
|
|
66
|
+
return await this.list({ authorId, limit })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Finds a post by its ID.
|
|
71
|
+
*
|
|
72
|
+
* @param postId - The ID of the post to retrieve.
|
|
73
|
+
* @returns The post or `undefined` if not found.
|
|
74
|
+
*/
|
|
75
|
+
async findById (postId: number): Promise<Post | undefined> {
|
|
76
|
+
return await this
|
|
77
|
+
.database
|
|
78
|
+
.select(this.selectWithAuthor())
|
|
79
|
+
.from(posts)
|
|
80
|
+
.innerJoin(users, eq(posts.authorId, users.id))
|
|
81
|
+
.where(eq(posts.id, postId))
|
|
82
|
+
.get() as Post | undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Creates a new post.
|
|
87
|
+
*
|
|
88
|
+
* @param post - The post to create.
|
|
89
|
+
* @returns The ID of the created post.
|
|
90
|
+
*/
|
|
91
|
+
async create (post: PostCreateModel): Promise<bigint | undefined> {
|
|
92
|
+
const result = await this.database.insert(posts).values(post)
|
|
93
|
+
return result.lastInsertRowid
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Updates a post by its ID.
|
|
98
|
+
*
|
|
99
|
+
* @param postId - The ID of the post to update.
|
|
100
|
+
* @param post - The updated post data.
|
|
101
|
+
* @returns The updated post or `undefined` if not found.
|
|
102
|
+
*/
|
|
103
|
+
async update (postId: number, post: Partial<PostModel>): Promise<boolean> {
|
|
104
|
+
const result = await this.database.update(posts).set(post).where(eq(posts.id, postId))
|
|
105
|
+
return isNotEmpty<bigint>(result.lastInsertRowid) && result.lastInsertRowid > 0
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Deletes a post by its ID.
|
|
110
|
+
*
|
|
111
|
+
* @param postId - The ID of the post to delete.
|
|
112
|
+
* @returns `true` if the post was deleted, otherwise `false`.
|
|
113
|
+
*/
|
|
114
|
+
async delete (postId: number): Promise<boolean> {
|
|
115
|
+
const result = await this.database.delete(posts).where(eq(posts.id, postId)).run()
|
|
116
|
+
return isNotEmpty<bigint>(result.lastInsertRowid) && result.lastInsertRowid > 0
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Selects posts with author information.
|
|
121
|
+
*/
|
|
122
|
+
private selectWithAuthor (): Record<string, any> {
|
|
123
|
+
return {
|
|
124
|
+
id: posts.id,
|
|
125
|
+
title: posts.title,
|
|
126
|
+
content: posts.content,
|
|
127
|
+
createdAt: posts.createdAt,
|
|
128
|
+
updatedAt: posts.updatedAt,
|
|
129
|
+
author: {
|
|
130
|
+
id: users.id,
|
|
131
|
+
name: users.name,
|
|
132
|
+
email: users.email,
|
|
133
|
+
createdAt: users.createdAt,
|
|
134
|
+
updatedAt: users.updatedAt
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { desc, eq } from 'drizzle-orm'
|
|
2
|
+
import { Stone } from '@stone-js/core'
|
|
3
|
+
import { UserModel } from '../models/User'
|
|
4
|
+
import { Session } from '../models/Session'
|
|
5
|
+
import { sessions } from '../database/schema'
|
|
6
|
+
import { LibSQLDatabase } from 'drizzle-orm/libsql'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Session Session Repository Options
|
|
10
|
+
*/
|
|
11
|
+
export interface SessionRepositoryOptions {
|
|
12
|
+
database: LibSQLDatabase
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Session Session Repository
|
|
17
|
+
*
|
|
18
|
+
* Manages session session persistence in the database.
|
|
19
|
+
*/
|
|
20
|
+
@Stone({ alias: 'sessionRepository' })
|
|
21
|
+
export class SessionRepository {
|
|
22
|
+
private readonly database: LibSQLDatabase
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create a new instance of SessionRepository
|
|
26
|
+
*
|
|
27
|
+
* @param options - The options to create the repository
|
|
28
|
+
*/
|
|
29
|
+
constructor ({ database }: SessionRepositoryOptions) {
|
|
30
|
+
this.database = database
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* List sessions
|
|
35
|
+
*
|
|
36
|
+
* @param limit - The limit of sessions to list
|
|
37
|
+
* @returns The list of sessions
|
|
38
|
+
*/
|
|
39
|
+
async list (limit: number): Promise<Session[]> {
|
|
40
|
+
return await this
|
|
41
|
+
.database
|
|
42
|
+
.select()
|
|
43
|
+
.from(sessions)
|
|
44
|
+
.orderBy(desc(sessions.createdAt))
|
|
45
|
+
.limit(limit)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* List sessions
|
|
50
|
+
*
|
|
51
|
+
* @param limit - The limit of sessions to list
|
|
52
|
+
* @returns The list of sessions
|
|
53
|
+
*/
|
|
54
|
+
async listByUser (user: UserModel, limit: number): Promise<Session[]> {
|
|
55
|
+
return await this
|
|
56
|
+
.database
|
|
57
|
+
.select()
|
|
58
|
+
.from(sessions)
|
|
59
|
+
.where(eq(sessions.userId, user.id))
|
|
60
|
+
.orderBy(desc(sessions.createdAt))
|
|
61
|
+
.limit(limit)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Find a session by ID
|
|
66
|
+
*
|
|
67
|
+
* @param id - The ID of the session to find
|
|
68
|
+
* @returns The session or undefined if not found
|
|
69
|
+
*/
|
|
70
|
+
async findById (id: number): Promise<Session | undefined> {
|
|
71
|
+
const result = await this.database.select().from(sessions).where(eq(sessions.id, id)).get()
|
|
72
|
+
return result ?? undefined
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Retrieves the latest session for a given user.
|
|
77
|
+
*
|
|
78
|
+
* @param user - The user whose last session is being retrieved.
|
|
79
|
+
* @returns The latest session or `undefined` if none exists.
|
|
80
|
+
*/
|
|
81
|
+
async getLatest (user: UserModel): Promise<Session | undefined> {
|
|
82
|
+
return await this.database
|
|
83
|
+
.select()
|
|
84
|
+
.from(sessions)
|
|
85
|
+
.where(eq(sessions.userId, user.id))
|
|
86
|
+
.orderBy(desc(sessions.createdAt))
|
|
87
|
+
.limit(1)
|
|
88
|
+
.get()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create a session
|
|
93
|
+
*
|
|
94
|
+
* @param session - The session to create
|
|
95
|
+
* @returns The ID of the created session
|
|
96
|
+
*/
|
|
97
|
+
async create (session: Omit<Session, 'id'>): Promise<Session> {
|
|
98
|
+
return await this.database.insert(sessions).values(session).returning().get()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Update a session
|
|
103
|
+
*
|
|
104
|
+
* @param id - The ID of the session to update
|
|
105
|
+
* @param session - The session data to update
|
|
106
|
+
* @returns The updated session or undefined if not found
|
|
107
|
+
*/
|
|
108
|
+
async update (id: number, session: Partial<Session>): Promise<Session | undefined> {
|
|
109
|
+
const result = await this.database.update(sessions).set(session).where(eq(sessions.id, id)).returning().get()
|
|
110
|
+
return result ?? undefined
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Delete a session
|
|
115
|
+
*
|
|
116
|
+
* @param id - The ID of the session to delete
|
|
117
|
+
* @returns `true` if the session was deleted, `false` if the session was not found
|
|
118
|
+
*/
|
|
119
|
+
async delete (id: number): Promise<boolean> {
|
|
120
|
+
const result = await this.database.delete(sessions).where(eq(sessions.id, id)).run()
|
|
121
|
+
return result.rowsAffected > 0
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { eq } from 'drizzle-orm'
|
|
2
|
+
import { Stone } from '@stone-js/core'
|
|
3
|
+
import { users } from '../database/schema'
|
|
4
|
+
import { UserModel } from '../models/User'
|
|
5
|
+
import { LibSQLDatabase } from 'drizzle-orm/libsql'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* User Repository Options
|
|
9
|
+
*/
|
|
10
|
+
export interface UserRepositoryOptions {
|
|
11
|
+
database: LibSQLDatabase
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* User Repository
|
|
16
|
+
*
|
|
17
|
+
* @Stone() is a decorator that marks a class as a Stone component.
|
|
18
|
+
* @Stone() Think of it like a Bean in Spring or a Component in Angular.
|
|
19
|
+
* The alias is required to get benefits of destructuring Dependency Injection.
|
|
20
|
+
*/
|
|
21
|
+
@Stone({ alias: 'userRepository' })
|
|
22
|
+
export class UserRepository {
|
|
23
|
+
private readonly database: LibSQLDatabase
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a new instance of UserRepository
|
|
27
|
+
*
|
|
28
|
+
* @param options - The options to create the repository
|
|
29
|
+
*/
|
|
30
|
+
constructor ({ database }: UserRepositoryOptions) {
|
|
31
|
+
this.database = database
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* List users
|
|
36
|
+
*
|
|
37
|
+
* @param limit - The limit of users to list
|
|
38
|
+
* @returns The list of users
|
|
39
|
+
*/
|
|
40
|
+
async list (limit: number): Promise<UserModel[]> {
|
|
41
|
+
return await this.database.select().from(users).limit(limit)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Find a user by ID
|
|
46
|
+
*
|
|
47
|
+
* @param id - The ID of the user to find
|
|
48
|
+
* @returns The user or undefined if not found
|
|
49
|
+
*/
|
|
50
|
+
async findById (id: number): Promise<UserModel | undefined> {
|
|
51
|
+
const result = await this.database.select().from(users).where(eq(users.id, id)).get()
|
|
52
|
+
return result ?? undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Find a user by dynamic conditions
|
|
57
|
+
*
|
|
58
|
+
* @param conditions - Conditions to match the user
|
|
59
|
+
* @returns The user or undefined if not found
|
|
60
|
+
*/
|
|
61
|
+
async findBy (conditions: Partial<UserModel>): Promise<UserModel | undefined> {
|
|
62
|
+
const result = await this.database.select().from(users).where(eq(users.email, conditions.email ?? '')).get()
|
|
63
|
+
return result ?? undefined
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a user
|
|
68
|
+
*
|
|
69
|
+
* @param user - The user to create
|
|
70
|
+
* @returns The ID of the created user
|
|
71
|
+
*/
|
|
72
|
+
async create (user: Omit<UserModel, 'id'>): Promise<bigint | undefined> {
|
|
73
|
+
const result = await this.database.insert(users).values(user)
|
|
74
|
+
return result.lastInsertRowid
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Update a user
|
|
79
|
+
*
|
|
80
|
+
* @param id - The ID of the user to update
|
|
81
|
+
* @param user - The user data to update
|
|
82
|
+
* @returns The updated user or undefined if not found
|
|
83
|
+
*/
|
|
84
|
+
async update (id: number, user: Partial<UserModel>): Promise<UserModel | undefined> {
|
|
85
|
+
const result = await this.database.update(users).set(user).where(eq(users.id, id)).returning().get()
|
|
86
|
+
return result ?? undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Delete a user
|
|
91
|
+
*
|
|
92
|
+
* @param id - The ID of the user to delete
|
|
93
|
+
* @returns `true` if the user was deleted, `false` if the user was not found
|
|
94
|
+
*/
|
|
95
|
+
async delete (id: number): Promise<boolean> {
|
|
96
|
+
const result = await this.database.delete(users).where(eq(users.id, id)).run()
|
|
97
|
+
return result.rowsAffected > 0
|
|
98
|
+
}
|
|
99
|
+
}
|