$30 off During Our Annual Pro Sale. View Details »

From Desktop to web and back

From Desktop to web and back

Ever wondered how desktop and web technologies in .NET have influenced each other, and how the web technologies in .NET evolved? In this talk, "From Desktop to Web and Back," we explore this evolution. Fabian Gosebrink walks us through .NET's transformation, the rise of web patterns, and the synergy between frontend and backend. Learn about ASP.NET Core's role in robust backend systems and Angular's dynamic frontend capabilities. From API essentials to Angular components, this talk provides a guide for navigating the crossroads of desktop and web development. Fabian Gosebrink takes us on a tech journey, highlighting the convergence of desktop and web for the future of app development.

Fabian Gosebrink

December 13, 2023
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. <Window x:Class="WPFViewModelAsFacade.MainWindow" xmlns="..." xmlns:x="..." Title="MainWindow" Height="350" Width="525"> <Grid> <TextBlock Text="{Binding

    CalculatedNumber}"> </TextBlock> </Grid> </Window> 1 2 3 4 5 6 7 8 9 10 11 12 Text="{Binding CalculatedNumber}"> <Window x:Class="WPFViewModelAsFacade.MainWindow" 1 xmlns="..." 2 xmlns:x="..." 3 Title="MainWindow" 4 Height="350" 5 Width="525"> 6 <Grid> 7 <TextBlock 8 9 </TextBlock> 10 </Grid> 11 </Window> 12
  2. public class MainViewModel { private readonly ICalculationService _calculationService; //other Properties

    here... public int CalculatedNumber { get { return _calculationService.CalcNumber; } } public MainViewModel(ICalculationService calculationService) { _calculationService = calculationService; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  3. var myViewModel = { personName: 'Bob', personAge: 123 }; ko.applyBindings(myViewModel);

    The name is <span data-bind="text: personName"></span> 1 2 3 4 5 6 7 8 9
  4. var myViewModel = { personName: 'Bob', personAge: 123 }; ko.applyBindings(myViewModel);

    The name is <span data-bind="text: personName"></span> 1 2 3 4 5 6 7 8 9 var myViewModel = { personName: 'Bob', personAge: 123 }; 1 2 3 4 5 ko.applyBindings(myViewModel); 6 7 8 The name is <span data-bind="text: personName"></span> 9
  5. var myViewModel = { personName: 'Bob', personAge: 123 }; ko.applyBindings(myViewModel);

    The name is <span data-bind="text: personName"></span> 1 2 3 4 5 6 7 8 9 var myViewModel = { personName: 'Bob', personAge: 123 }; 1 2 3 4 5 ko.applyBindings(myViewModel); 6 7 8 The name is <span data-bind="text: personName"></span> 9 ko.applyBindings(myViewModel); var myViewModel = { 1 personName: 'Bob', 2 personAge: 123 3 }; 4 5 6 7 8 The name is <span data-bind="text: personName"></span> 9
  6. var myViewModel = { personName: 'Bob', personAge: 123 }; ko.applyBindings(myViewModel);

    The name is <span data-bind="text: personName"></span> 1 2 3 4 5 6 7 8 9 var myViewModel = { personName: 'Bob', personAge: 123 }; 1 2 3 4 5 ko.applyBindings(myViewModel); 6 7 8 The name is <span data-bind="text: personName"></span> 9 ko.applyBindings(myViewModel); var myViewModel = { 1 personName: 'Bob', 2 personAge: 123 3 }; 4 5 6 7 8 The name is <span data-bind="text: personName"></span> 9 The name is <span data-bind="text: personName"></span> var myViewModel = { 1 personName: 'Bob', 2 personAge: 123 3 }; 4 5 ko.applyBindings(myViewModel); 6 7 8 9
  7. <!doctype html> <html ng-app> <head> <script src="https://.../angularjs/1.8.2/angular.min.js"></script> </head> <body> <div>

    <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <h1>Hello {{yourName}}!</h1> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  8. <!doctype html> <html ng-app> <head> <script src="https://.../angularjs/1.8.2/angular.min.js"></script> </head> <body> <div>

    <label>Name:</label> <input type="text" ng-model="yourName" placeholder="Enter a name here"> <hr> <h1>Hello {{yourName}}!</h1> </div> </body> </html> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <h1>Hello {{yourName}}!</h1> <!doctype html> 1 <html ng-app> 2 <head> 3 <script src="https://.../angularjs/1.8.2/angular.min.js"></script> 4 </head> 5 <body> 6 <div> 7 <label>Name:</label> 8 <input type="text" ng-model="yourName" placeholder="Enter a name here"> 9 <hr> 10 11 </div> 12 </body> 13 </html> 14
  9. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11
  10. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 1 2 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11
  11. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 1 2 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.get('/', (req, res) => { res.send('Hello World!') }) const express = require('express') 1 const app = express() 2 const port = 3000 3 4 5 6 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11
  12. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 1 2 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.get('/', (req, res) => { res.send('Hello World!') }) const express = require('express') 1 const app = express() 2 const port = 3000 3 4 5 6 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.listen(port, () => { console.log(`Example app on port ${port}`) }); const express = require('express') 1 const app = express() 2 const port = 3000 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 9 10 11
  13. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 1 2 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.get('/', (req, res) => { res.send('Hello World!') }) const express = require('express') 1 const app = express() 2 const port = 3000 3 4 5 6 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.listen(port, () => { console.log(`Example app on port ${port}`) }); const express = require('express') 1 const app = express() 2 const port = 3000 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11
  14. const express = require('express') const app = express() const port

    = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 1 2 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.get('/', (req, res) => { res.send('Hello World!') }) const express = require('express') 1 const app = express() 2 const port = 3000 3 4 5 6 7 8 app.listen(port, () => { 9 console.log(`Example app on port ${port}`) 10 }); 11 app.listen(port, () => { console.log(`Example app on port ${port}`) }); const express = require('express') 1 const app = express() 2 const port = 3000 3 4 app.get('/', (req, res) => { 5 res.send('Hello World!') 6 }) 7 8 9 10 11 const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11 node app.js 1
  15. dotnet new ... 1 2 dotnet run 3 dotnet run

    dotnet new ... 1 2 3 node app.js
  16. dotnet new ... 1 2 dotnet run 3 dotnet run

    dotnet new ... 1 2 3 dotnet new ... dotnet run 1 2 3 node app.js
  17. var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", ()

    => "Hello World!"); app.Run(); 1 2 3 4 5 6 var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6
  18. var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", ()

    => "Hello World!"); app.Run(); 1 2 3 4 5 6 var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6 var app = builder.Build(); var builder = WebApplication.CreateBuilder(args); 1 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6
  19. var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", ()

    => "Hello World!"); app.Run(); 1 2 3 4 5 6 var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6 var app = builder.Build(); var builder = WebApplication.CreateBuilder(args); 1 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6 app.MapGet("/", () => "Hello World!"); var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 4 5 app.Run(); 6
  20. var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", ()

    => "Hello World!"); app.Run(); 1 2 3 4 5 6 var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6 var app = builder.Build(); var builder = WebApplication.CreateBuilder(args); 1 2 3 app.MapGet("/", () => "Hello World!"); 4 5 app.Run(); 6 app.MapGet("/", () => "Hello World!"); var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 4 5 app.Run(); 6 app.Run(); var builder = WebApplication.CreateBuilder(args); 1 var app = builder.Build(); 2 3 app.MapGet("/", () => "Hello World!"); 4 5 6
  21. var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", ()

    => "Hello World!"); app.Run(); 1 2 3 4 5 6 const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app on port ${port}`) }); 1 2 3 4 5 6 7 8 9 10 11
  22. { "id": 1, "name": "Lasagne", "type": "Starter", "calories": 1000, "created":

    "2020-02-23T15:42:45.4923318+01:00" } 1 2 3 4 5 6 7
  23. { "id": 1, "name": "Lasagne", "type": "Starter", "calories": 1000, "created":

    "2020-02-23T15:42:45.4923318+01:00", "links": [ { "href": "https://localhost:5001/api/v1/foods/1", "rel": "self", "method": "GET" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "delete_food", "method": "DELETE" }, { "href": "https://localhost:5001/api/v1/foods", "rel": "create_food", "method": "POST" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "update_food", "method": "PUT" } ] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
  24. { "id": 1, "name": "Lasagne", "type": "Starter", "calories": 1000, "created":

    "2020-02-23T15:42:45.4923318+01:00", "links": [ { "href": "https://localhost:5001/api/v1/foods/1", "rel": "self", "method": "GET" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "delete_food", "method": "DELETE" }, { "href": "https://localhost:5001/api/v1/foods", "rel": "create_food", "method": "POST" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "update_food", "method": "PUT" } ] } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 "links": [ { "href": "https://localhost:5001/api/v1/foods/1", "rel": "self", "method": "GET" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "delete_food", "method": "DELETE" }, { "href": "https://localhost:5001/api/v1/foods", "rel": "create_food", "method": "POST" }, { "href": "https://localhost:5001/api/v1/foods/1", "rel": "update_food", "method": "PUT" } ] { 1 "id": 1, 2 "name": "Lasagne", 3 "type": "Starter", 4 "calories": 1000, 5 "created": "2020-02-23T15:42:45.4923318+01:00", 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 } 29
  25. @Component({ selector: 'app-layout', templateUrl: './layout.component.html', styleUrls: ['./layout.component.scss'], standalone: true, imports:

    [...], }) export class LayoutComponent { private readonly someDep = inject(MyService); login(): void { // ... } logout(): void { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  26. @Component({ /* ... */ }) export class DoggoRateComponent { @Input()

    currentDoggo: Doggo | null = null; @Output() rated = new EventEmitter<number>(); @Output() skipped = new EventEmitter(); } 1 2 3 4 5 6 7 8
  27. @if(loading()) { <div>Loading...</div> } @else { <app-doggo-rate [currentDoggo]="selectedDoggo()" (rated)="rateDoggo($event)" (skipped)="skipDoggo()"

    ></app-doggo-rate> <app-doggo-list [doggos]="doggos()" (doggoSelected)="selectDoggo($event)" ></app-doggo-list> } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  28. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
  29. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30
  30. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 6 7 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30
  31. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 6 7 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 10 11 12 13 14 15 16 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30
  32. @Component({ /* ... */ }) export class MainDoggoComponent implements OnInit

    { private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private readonly store = inject(Store); private readonly destroyRef = inject(DestroyRef); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 3 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 doggos = this.store.selectSignal(getAllDoggosButSelected); selectedDoggo = this.store.selectSignal(getSelectedDoggo); loading = this.store.selectSignal(getLoading); @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 6 7 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 ngOnInit(): void { this.store.dispatch(DoggosActions.loadDoggos()); this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); this.destroyRef.onDestroy(() => { this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); }); } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 10 11 12 13 14 15 16 17 18 rateDoggo(rating: number) { 19 this.store.dispatch(DoggosActions.rateDoggo({ rating })); 20 } 21 22 skipDoggo() { 23 this.store.dispatch(DoggosActions.selectNextDoggo()); 24 } 25 26 selectDoggo(id: string) { 27 this.store.dispatch(DoggosActions.selectDoggo({ id })); 28 } 29 } 30 rateDoggo(rating: number) { this.store.dispatch(DoggosActions.rateDoggo({ rating })); } skipDoggo() { this.store.dispatch(DoggosActions.selectNextDoggo()); } selectDoggo(id: string) { this.store.dispatch(DoggosActions.selectDoggo({ id })); } @Component({ /* ... */ }) 1 export class MainDoggoComponent implements OnInit { 2 private readonly store = inject(Store); 3 private readonly destroyRef = inject(DestroyRef); 4 5 doggos = this.store.selectSignal(getAllDoggosButSelected); 6 selectedDoggo = this.store.selectSignal(getSelectedDoggo); 7 loading = this.store.selectSignal(getLoading); 8 9 ngOnInit(): void { 10 this.store.dispatch(DoggosActions.loadDoggos()); 11 this.store.dispatch(DoggosActions.startListeningToRealtimeDoggoEvents()); 12 13 this.destroyRef.onDestroy(() => { 14 this.store.dispatch(DoggosActions.stopListeningToRealtimeDoggoEvents()); 15 }); 16 } 17 18 19 20 21 22 23 24 25 26 27 28 29 } 30
  33. App About Doggos Feature Feature Domain type:feature Ui type:ui type:domain

    Utils type:utils type:feature Shared util-environments type:util util-Auth type:util util-Common type:util UI-common type:ui scope:about scope:doggos scope:shared
  34. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
  35. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30
  36. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30
  37. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 g [ / ],
  38. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { 31 "sourceTag": "scope:shared", 32 "onlyDependOnLibsWithTags": ["scope:shared"] 33 @ / [
  39. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 23 24 25 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { 31 "sourceTag": "scope:shared", 32 "onlyDependOnLibsWithTags": ["scope:shared"] 33 }, 34 { 35 "sourceTag": "type:app", 36 "onlyDependOnLibsWithTags": [ 37 "type:feature", 38 "type:util", 39 [],
  40. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 23 24 25 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 27 28 29 30 { 31 "sourceTag": "scope:shared", 32 "onlyDependOnLibsWithTags": ["scope:shared"] 33 }, 34 { 35 "sourceTag": "type:app", 36 "onlyDependOnLibsWithTags": [ 37 "type:feature", 38 "type:util", 39 "type:ui" 40 ] 41 }, 42 { 43 y p g [
  41. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 23 24 25 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 27 28 29 30 { "sourceTag": "scope:shared", "onlyDependOnLibsWithTags": ["scope:shared"] }, "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 31 32 33 34 { 35 "sourceTag": "type:app", 36 "onlyDependOnLibsWithTags": [ 37 "type:feature", 38 "type:util", 39 "type:ui" 40 ] 41 }, 42 { 43 "sourceTag": "type:feature", 44 "onlyDependOnLibsWithTags": [ 45 "type:domain", 46 "type:ui", 47 {
  42. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 23 24 25 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 27 28 29 30 { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "type:app", "onlyDependOnLibsWithTags": [ "type:feature", "type:util", "type:ui" ] }, "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { 31 "sourceTag": "scope:shared", 32 "onlyDependOnLibsWithTags": ["scope:shared"] 33 }, 34 35 36 37 38 39 40 41 42 { 43 "sourceTag": "type:feature", 44 "onlyDependOnLibsWithTags": [ 45 "type:domain", 46 "type:ui", 47 "type:util" 48 ] 49 }, 50 { 51 "sourceTag": "type:ui", 52 "onlyDependOnLibsWithTags": ["type:util", "type:domain"] 53
  43. { "root": true, "ignorePatterns": ["**/*"], "plugins": ["@nx"], "overrides": [ {

    "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "rules": { "@nx/enforce-module-boundaries": [ "error", { "enforceBuildableLibDependency": true, "allow": [], "depConstraints": [ { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "@nx/enforce-module-boundaries": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "error", { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 "depConstraints": [ { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggo-rating-app", "onlyDependOnLibsWithTags": [ "scope:doggos", "scope:about", "scope:shared" ] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 15 16 17 18 19 20 21 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:about", "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 23 24 25 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "scope:doggos", "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] }, { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 27 28 29 30 { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { 1 "root": true, 2 "ignorePatterns": ["**/*"], 3 "plugins": ["@nx"], 4 "overrides": [ 5 { 6 "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 "rules": { 8 "@nx/enforce-module-boundaries": [ 9 "error", 10 { 11 "enforceBuildableLibDependency": true, 12 "allow": [], 13 "depConstraints": [ 14 { 15 "sourceTag": "scope:doggo-rating-app", 16 "onlyDependOnLibsWithTags": [ 17 "scope:doggos", 18 "scope:about", 19 "scope:shared" 20 ] 21 }, 22 { 23 "sourceTag": "scope:about", 24 "onlyDependOnLibsWithTags": ["scope:about", "scope:shared"] 25 }, 26 { 27 "sourceTag": "scope:doggos", 28 "onlyDependOnLibsWithTags": ["scope:doggos", "scope:shared"] 29 }, 30 { "sourceTag": "type:feature", "onlyDependOnLibsWithTags": [ "type:domain", "type:ui", "type:util" ] }, { 31 "sourceTag": "scope:shared", 32 "onlyDependOnLibsWithTags": ["scope:shared"] 33 }, 34 { 35 "sourceTag": "type:app", 36 "onlyDependOnLibsWithTags": [ 37 "type:feature", 38 "type:util", 39 "type:ui" 40 ] 41 }, 42 43 44 45 46 47 48 49 50 { 51 "sourceTag": "type:ui", 52 "onlyDependOnLibsWithTags": ["type:util", "type:domain"] 53 }, 54 { 55 "sourceTag": "type:domain", 56 "onlyDependOnLibsWithTags": ["type:util"] 57 } 58 ] 59 } 60
  44. export function cameraFactory( platformInformationService: PlatformInformationService ): AbstractCameraService { return platformInformationService.isMobile

    ? new MobileCameraService() : new DesktopCameraService(); } @Injectable({ providedIn: 'root', useFactory: cameraFactory, deps: [PlatformInformationService], }) export abstract class CameraService { abstract getPhoto(...): Observable<Photo>; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  45. import { AbstractCameraService, Photo } from '@workspace/features/camera'; @Component({ ... })

    export class ProfileDetailsComponent { private readonly cameraService = inject(CameraService); pictureClicked() { this.cameraService.getPhoto() .subscribe((result: Photo) => { // ... }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16