From 1e7070376764a133cb11459310b23c221a40f37c Mon Sep 17 00:00:00 2001 From: stefanoslig Date: Tue, 24 Dec 2024 18:46:08 +0100 Subject: [PATCH] refactor: start using withProps for the dependencies --- .github/workflows/production.yml | 31 --- .../articles/data-access/src/article.store.ts | 194 +++++++++--------- .../data-access/src/articles-list.store.ts | 14 +- libs/auth/data-access/src/auth.store.ts | 119 +++++------ .../src/lib/error-handler.store.ts | 11 +- libs/home/feature-home/src/home.store.ts | 9 +- libs/profile/data-access/src/profile.store.ts | 14 +- package-lock.json | 16 +- package.json | 4 +- 9 files changed, 197 insertions(+), 215 deletions(-) delete mode 100644 .github/workflows/production.yml diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml deleted file mode 100644 index 72681a6b..00000000 --- a/.github/workflows/production.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: 'ci-cd pipeline' - -on: - push: - branches: - - main - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Use Node.js 20.x - uses: actions/setup-node@v3 - with: - node-version: 20.x - cache: 'npm' - cache-dependency-path: package-lock.json - - name: Install dependencies - run: npm ci - - name: Build file - run: nx run conduit:build - - - name: Deploy production to Netlify - uses: South-Paw/action-netlify-deploy@v1.2.1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - netlify-auth-token: ${{ secrets.NETLIFY_AUTH_TOKEN }} - netlify-site-id: ${{ secrets.NETLIFY_SITE_ID }} - build-dir: './build' - comment-on-commit: true diff --git a/libs/articles/data-access/src/article.store.ts b/libs/articles/data-access/src/article.store.ts index 22d3b443..1ed42fea 100644 --- a/libs/articles/data-access/src/article.store.ts +++ b/libs/articles/data-access/src/article.store.ts @@ -1,4 +1,4 @@ -import { signalStore, withState, withMethods, patchState } from '@ngrx/signals'; +import { signalStore, withState, withMethods, patchState, withProps } from '@ngrx/signals'; import { ArticleState, articleInitialState } from './models/article.model'; import { inject } from '@angular/core'; import { ArticlesService } from './services/articles.service'; @@ -14,126 +14,122 @@ import { FormErrorsStore } from '@realworld/core/forms'; export const ArticleStore = signalStore( { providedIn: 'root' }, withState(articleInitialState), - withMethods( - ( - store, - articlesService = inject(ArticlesService), - actionsService = inject(ActionsService), - router = inject(Router), - formErrorsStore = inject(FormErrorsStore), - ) => ({ - getArticle: rxMethod( - pipe( - tap(() => setLoading('getArticle')), - switchMap((slug) => - articlesService.getArticle(slug).pipe( - tapResponse({ - next: ({ article }) => { - patchState(store, { data: article, ...setLoaded('getArticle') }); - }, - error: () => { - patchState(store, { data: articleInitialState.data, ...setLoaded('getArticle') }); - }, - }), - ), + withProps(() => ({ + _articlesService: inject(ArticlesService), + _actionsService: inject(ActionsService), + _router: inject(Router), + _formErrorsStore: inject(FormErrorsStore), + })), + withMethods((store) => ({ + getArticle: rxMethod( + pipe( + tap(() => setLoading('getArticle')), + switchMap((slug) => + store._articlesService.getArticle(slug).pipe( + tapResponse({ + next: ({ article }) => { + patchState(store, { data: article, ...setLoaded('getArticle') }); + }, + error: () => { + patchState(store, { data: articleInitialState.data, ...setLoaded('getArticle') }); + }, + }), ), ), ), - getComments: rxMethod( - pipe( - tap(() => setLoading('getComments')), - switchMap((slug) => - articlesService.getComments(slug).pipe( - tapResponse({ - next: ({ comments }) => { - patchState(store, { comments: comments }); - setLoaded('getComments'); - }, - error: () => { - patchState(store, { comments: articleInitialState.comments }); - setLoaded('getComments'); - }, - }), - ), + ), + getComments: rxMethod( + pipe( + tap(() => setLoading('getComments')), + switchMap((slug) => + store._articlesService.getComments(slug).pipe( + tapResponse({ + next: ({ comments }) => { + patchState(store, { comments: comments }); + setLoaded('getComments'); + }, + error: () => { + patchState(store, { comments: articleInitialState.comments }); + setLoaded('getComments'); + }, + }), ), ), ), - followUser: rxMethod( - pipe( - switchMap((username) => actionsService.followUser(username)), - tap(({ profile }) => patchState(store, { data: { ...store.data(), author: profile } })), - ), + ), + followUser: rxMethod( + pipe( + switchMap((username) => store._actionsService.followUser(username)), + tap(({ profile }) => patchState(store, { data: { ...store.data(), author: profile } })), ), - unfollowUser: rxMethod( - pipe( - switchMap((username) => actionsService.unfollowUser(username)), - tap(({ profile }) => patchState(store, { data: { ...store.data(), author: profile } })), - ), + ), + unfollowUser: rxMethod( + pipe( + switchMap((username) => store._actionsService.unfollowUser(username)), + tap(({ profile }) => patchState(store, { data: { ...store.data(), author: profile } })), ), - deleteComment: rxMethod<{ commentId: number; slug: string }>( - pipe( - switchMap(({ commentId, slug }) => - articlesService - .deleteComment(commentId, slug) - .pipe( - tap(() => patchState(store, { comments: store.comments().filter((item) => item.id !== commentId) })), - ), - ), + ), + deleteComment: rxMethod<{ commentId: number; slug: string }>( + pipe( + switchMap(({ commentId, slug }) => + store._articlesService + .deleteComment(commentId, slug) + .pipe(tap(() => patchState(store, { comments: store.comments().filter((item) => item.id !== commentId) }))), ), ), - deleteArticle: rxMethod( - pipe( - switchMap((slug) => - articlesService.deleteArticle(slug).pipe( - tapResponse({ - next: () => router.navigate(['/']), - error: () => patchState(store, articleInitialState), - }), - ), + ), + deleteArticle: rxMethod( + pipe( + switchMap((slug) => + store._articlesService.deleteArticle(slug).pipe( + tapResponse({ + next: () => store._router.navigate(['/']), + error: () => patchState(store, articleInitialState), + }), ), ), ), - addComment: rxMethod( - pipe( - switchMap((addedComment) => - articlesService.addComment(store.data.slug(), addedComment).pipe( - tapResponse({ - next: ({ comment }) => patchState(store, { comments: [comment, ...store.comments()] }), - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + addComment: rxMethod( + pipe( + switchMap((addedComment) => + store._articlesService.addComment(store.data.slug(), addedComment).pipe( + tapResponse({ + next: ({ comment }) => patchState(store, { comments: [comment, ...store.comments()] }), + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - publishArticle: rxMethod( - pipe( - switchMap((article) => - articlesService.publishArticle(article).pipe( - tapResponse({ - next: ({ article }) => router.navigate(['article', article.slug]), - error: ({ error }) => formErrorsStore.setErrors({ errors: error.errors }), - }), - ), + ), + publishArticle: rxMethod( + pipe( + switchMap((article) => + store._articlesService.publishArticle(article).pipe( + tapResponse({ + next: ({ article }) => store._router.navigate(['article', article.slug]), + error: ({ error }) => store._formErrorsStore.setErrors({ errors: error.errors }), + }), ), ), ), - editArticle: rxMethod( - pipe( - switchMap((article) => - articlesService.editArticle(article).pipe( - tapResponse({ - next: ({ article }) => router.navigate(['article', article.slug]), - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + editArticle: rxMethod( + pipe( + switchMap((article) => + store._articlesService.editArticle(article).pipe( + tapResponse({ + next: ({ article }) => store._router.navigate(['article', article.slug]), + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - initializeArticle: () => { - patchState(store, articleInitialState); - }, - }), - ), + ), + initializeArticle: () => { + patchState(store, articleInitialState); + }, + })), withCallState({ collection: 'getArticle' }), withCallState({ collection: 'getComments' }), ); diff --git a/libs/articles/data-access/src/articles-list.store.ts b/libs/articles/data-access/src/articles-list.store.ts index dfba504d..fd0e736b 100644 --- a/libs/articles/data-access/src/articles-list.store.ts +++ b/libs/articles/data-access/src/articles-list.store.ts @@ -1,4 +1,4 @@ -import { signalStore, withState, withMethods, patchState, withComputed } from '@ngrx/signals'; +import { signalStore, withState, withMethods, patchState, withComputed, withProps } from '@ngrx/signals'; import { Articles, ArticlesListConfig, @@ -17,6 +17,10 @@ import { Article } from '@realworld/core/api-types'; export const ArticlesListStore = signalStore( { providedIn: 'root' }, withState(articlesListInitialState), + withProps(() => ({ + _articlesService: inject(ArticlesService), + _actionsService: inject(ActionsService), + })), withComputed(({ listConfig, articles }) => ({ totalPages: computed(() => Array.from( @@ -25,12 +29,12 @@ export const ArticlesListStore = signalStore( ), ), })), - withMethods((store, articlesService = inject(ArticlesService), actionsService = inject(ActionsService)) => ({ + withMethods((store) => ({ loadArticles: rxMethod( pipe( tap(() => setLoading('getArticles')), concatMap((listConfig) => - articlesService.query(listConfig).pipe( + store._articlesService.query(listConfig).pipe( tapResponse({ next: ({ articles, articlesCount }) => { patchState(store, { @@ -49,7 +53,7 @@ export const ArticlesListStore = signalStore( favouriteArticle: rxMethod( pipe( concatMap((slug) => - actionsService.favorite(slug).pipe( + store._actionsService.favorite(slug).pipe( tapResponse({ next: ({ article }) => { patchState(store, { @@ -67,7 +71,7 @@ export const ArticlesListStore = signalStore( unFavouriteArticle: rxMethod( pipe( concatMap((slug) => - actionsService.unfavorite(slug).pipe( + store._actionsService.unfavorite(slug).pipe( tapResponse({ next: ({ article }) => { patchState(store, { diff --git a/libs/auth/data-access/src/auth.store.ts b/libs/auth/data-access/src/auth.store.ts index d9edfa41..0e22d8e2 100644 --- a/libs/auth/data-access/src/auth.store.ts +++ b/libs/auth/data-access/src/auth.store.ts @@ -1,4 +1,4 @@ -import { signalStore, withState, withMethods, patchState } from '@ngrx/signals'; +import { signalStore, withState, withMethods, patchState, withProps } from '@ngrx/signals'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; import { AuthState, authInitialState, initialUserValue } from './auth.model'; import { inject } from '@angular/core'; @@ -13,75 +13,78 @@ import { FormErrorsStore } from '@realworld/core/forms'; export const AuthStore = signalStore( { providedIn: 'root' }, withState(authInitialState), - withMethods( - (store, formErrorsStore = inject(FormErrorsStore), authService = inject(AuthService), router = inject(Router)) => ({ - getUser: rxMethod( - pipe( - switchMap(() => authService.user()), - tap(({ user }) => patchState(store, { user, loggedIn: true, ...setLoaded('getUser') })), - ), + withProps(() => ({ + _formErrorsStore: inject(FormErrorsStore), + _authService: inject(AuthService), + _router: inject(Router), + })), + withMethods((store) => ({ + getUser: rxMethod( + pipe( + switchMap(() => store._authService.user()), + tap(({ user }) => patchState(store, { user, loggedIn: true, ...setLoaded('getUser') })), ), - login: rxMethod( - pipe( - exhaustMap((credentials) => - authService.login(credentials).pipe( - tapResponse({ - next: ({ user }) => { - patchState(store, { user, loggedIn: true }); - router.navigateByUrl('/'); - }, - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + login: rxMethod( + pipe( + exhaustMap((credentials) => + store._authService.login(credentials).pipe( + tapResponse({ + next: ({ user }) => { + patchState(store, { user, loggedIn: true }); + store._router.navigateByUrl('/'); + }, + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - register: rxMethod( - pipe( - exhaustMap((newUserData) => - authService.register(newUserData).pipe( - tapResponse({ - next: ({ user }) => { - patchState(store, { user, loggedIn: true }); - router.navigateByUrl('/'); - }, - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + register: rxMethod( + pipe( + exhaustMap((newUserData) => + store._authService.register(newUserData).pipe( + tapResponse({ + next: ({ user }) => { + patchState(store, { user, loggedIn: true }); + store._router.navigateByUrl('/'); + }, + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - updateUser: rxMethod( - pipe( - exhaustMap((user) => - authService.update(user).pipe( - tapResponse({ - next: ({ user }) => { - patchState(store, { user }); - router.navigate(['profile', user.username]); - }, - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + updateUser: rxMethod( + pipe( + exhaustMap((user) => + store._authService.update(user).pipe( + tapResponse({ + next: ({ user }) => { + patchState(store, { user }); + store._router.navigate(['profile', user.username]); + }, + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - logout: rxMethod( - pipe( - exhaustMap(() => - authService.logout().pipe( - tapResponse({ - next: () => { - patchState(store, { user: initialUserValue, loggedIn: false }); - router.navigateByUrl('login'); - }, - error: ({ error }) => formErrorsStore.setErrors(error.errors), - }), - ), + ), + logout: rxMethod( + pipe( + exhaustMap(() => + store._authService.logout().pipe( + tapResponse({ + next: () => { + patchState(store, { user: initialUserValue, loggedIn: false }); + store._router.navigateByUrl('login'); + }, + error: ({ error }) => store._formErrorsStore.setErrors(error.errors), + }), ), ), ), - }), - ), + ), + })), withCallState({ collection: 'getUser' }), ); diff --git a/libs/core/error-handler/src/lib/error-handler.store.ts b/libs/core/error-handler/src/lib/error-handler.store.ts index 04428a09..06aa9f27 100644 --- a/libs/core/error-handler/src/lib/error-handler.store.ts +++ b/libs/core/error-handler/src/lib/error-handler.store.ts @@ -1,4 +1,4 @@ -import { signalStore, withState, withMethods, patchState } from '@ngrx/signals'; +import { signalStore, withState, withMethods, patchState, withProps } from '@ngrx/signals'; import { inject } from '@angular/core'; import { Router } from '@angular/router'; import { ErrorHandlerState, errorHandlerInitialState } from './models/error-handler.state'; @@ -7,20 +7,23 @@ import { HttpErrorResponse } from '@angular/common/http'; export const ErrorHandlerStore = signalStore( { providedIn: 'root' }, withState(errorHandlerInitialState), - withMethods((store, router = inject(Router)) => ({ + withProps(() => ({ + _router: inject(Router), + })), + withMethods((store) => ({ handleError401: (error: HttpErrorResponse) => { patchState(store, { code: error.status, message: error.message, }); - router.navigate(['/login']); + store._router.navigate(['/login']); }, handleError404: (error: HttpErrorResponse) => { patchState(store, { code: error.status, message: error.message, }); - router.navigate(['/']); + store._router.navigate(['/']); }, })), ); diff --git a/libs/home/feature-home/src/home.store.ts b/libs/home/feature-home/src/home.store.ts index 4f7ca237..bb69445a 100644 --- a/libs/home/feature-home/src/home.store.ts +++ b/libs/home/feature-home/src/home.store.ts @@ -1,4 +1,4 @@ -import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals'; +import { signalStore, withState, withMethods, patchState, withHooks, withProps } from '@ngrx/signals'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; import { inject } from '@angular/core'; import { pipe, switchMap } from 'rxjs'; @@ -12,11 +12,14 @@ export interface HomeState { export const HomeStore = signalStore( { providedIn: 'root' }, withState({ tags: [] }), - withMethods((store, homeService = inject(HomeService)) => ({ + withProps(() => ({ + _homeService: inject(HomeService), + })), + withMethods((store) => ({ getTags: rxMethod( pipe( switchMap(() => - homeService.getTags().pipe( + store._homeService.getTags().pipe( tapResponse( (response) => { patchState(store, { tags: response.tags }); diff --git a/libs/profile/data-access/src/profile.store.ts b/libs/profile/data-access/src/profile.store.ts index a46db166..17037cd5 100644 --- a/libs/profile/data-access/src/profile.store.ts +++ b/libs/profile/data-access/src/profile.store.ts @@ -1,4 +1,4 @@ -import { patchState, signalStore, withMethods, withState } from '@ngrx/signals'; +import { patchState, signalStore, withMethods, withProps, withState } from '@ngrx/signals'; import { setLoaded, withCallState } from '@realworld/core/data-access'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; import { inject } from '@angular/core'; @@ -11,23 +11,27 @@ import { tapResponse } from '@ngrx/operators'; export const ProfileStore = signalStore( { providedIn: 'root' }, withState(profileInitialState), - withMethods((store, actionsService = inject(ActionsService), profileService = inject(ProfileService)) => ({ + withProps(() => ({ + _actionsService: inject(ActionsService), + _profileService: inject(ProfileService), + })), + withMethods((store) => ({ followUser: rxMethod( pipe( - switchMap((username) => actionsService.followUser(username)), + switchMap((username) => store._actionsService.followUser(username)), tap(({ profile }) => patchState(store, profile)), ), ), unfollowUser: rxMethod( pipe( - switchMap((username) => actionsService.unfollowUser(username)), + switchMap((username) => store._actionsService.unfollowUser(username)), tap(({ profile }) => patchState(store, profile)), ), ), getProfile: rxMethod( pipe( switchMap((username) => - profileService.getProfile(username).pipe( + store._profileService.getProfile(username).pipe( tapResponse({ next: (profile) => { patchState(store, { ...profile, ...setLoaded('getProfile') }); diff --git a/package-lock.json b/package-lock.json index ba8a5738..c8fdbdd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,8 +17,8 @@ "@angular/platform-browser": "19.0.1", "@angular/platform-browser-dynamic": "19.0.1", "@angular/router": "19.0.1", - "@ngrx/operators": "19.0.0-rc.0", - "@ngrx/signals": "19.0.0-rc.0", + "@ngrx/operators": "19.0.0", + "@ngrx/signals": "19.0.0", "@nx/angular": "20.2.2", "core-js": "3.31.0", "eslint-plugin-ngrx": "2.1.4", @@ -5650,9 +5650,9 @@ } }, "node_modules/@ngrx/operators": { - "version": "19.0.0-rc.0", - "resolved": "https://registry.npmjs.org/@ngrx/operators/-/operators-19.0.0-rc.0.tgz", - "integrity": "sha512-+KyX6sZydU3wMDUY8WH6m+n6WpkDO4pARS32dHg7QMYRSYniJwezWcJvTzuImTDUkoMPwKdaW9gUdPscfiCquw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/operators/-/operators-19.0.0.tgz", + "integrity": "sha512-IHh5bEjcubn3IZtm686tBfHctkgZESqu9Rgb76P+fsfTkLc4BEXlEBesIX8O6T0HS2OuTwOnyNRkWyexdZ0pmQ==", "dependencies": { "tslib": "^2.3.0" }, @@ -5661,9 +5661,9 @@ } }, "node_modules/@ngrx/signals": { - "version": "19.0.0-rc.0", - "resolved": "https://registry.npmjs.org/@ngrx/signals/-/signals-19.0.0-rc.0.tgz", - "integrity": "sha512-B9gxT1cvMGtrdLYk5UkIS8dDsjco2dmUC/t4jawwMaCt/ENWnBsUbSxaKggJYj3q+8+4n00Gmyut6lQX+9A9kw==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@ngrx/signals/-/signals-19.0.0.tgz", + "integrity": "sha512-Ktgq+wwIVH9HdobLOhrYF6VArIJYZa5lkgajUpSB9QuudpOLja9f7W2RAHQsMUBpQuREgFkTgIEr1vKIzDrGMA==", "dependencies": { "tslib": "^2.3.0" }, diff --git a/package.json b/package.json index d1472f93..0e027cbc 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ "@angular/platform-browser": "19.0.1", "@angular/platform-browser-dynamic": "19.0.1", "@angular/router": "19.0.1", - "@ngrx/operators": "19.0.0-rc.0", - "@ngrx/signals": "19.0.0-rc.0", + "@ngrx/operators": "19.0.0", + "@ngrx/signals": "19.0.0", "@nx/angular": "20.2.2", "core-js": "3.31.0", "eslint-plugin-ngrx": "2.1.4",