docs(architecture): add Architecture Decision Records (ADRs) documentation

Introduce a comprehensive guide for creating and maintaining ADRs
within the ISA-Frontend project. This includes an overview, structure,
naming conventions, and process guidelines to ensure consistent
documentation of architectural decisions.
This commit is contained in:
Lorenz Hilpert
2025-09-25 16:23:45 +02:00
parent 8391d0bd18
commit f2490b3421
3 changed files with 844 additions and 0 deletions

200
docs/architecture/README.md Normal file
View File

@@ -0,0 +1,200 @@
# Architecture Decision Records (ADRs)
## Overview
Architecture Decision Records (ADRs) are lightweight documents that capture important architectural decisions made during the development of the ISA-Frontend project. They provide context for why certain decisions were made, helping current and future team members understand the reasoning behind architectural choices.
## What are ADRs?
An Architecture Decision Record is a document that captures a single architectural decision and its rationale. The goal of an ADR is to document the architectural decisions that are being made so that:
- **Future team members** can understand why certain decisions were made
- **Current team members** can refer back to the reasoning behind decisions
- **Architectural evolution** can be tracked over time
- **Knowledge transfer** is facilitated during team changes
## ADR Structure
Each ADR follows a consistent structure based on our [TEMPLATE.md](./TEMPLATE.md) and includes:
- **Problem Statement**: What architectural challenge needs to be addressed
- **Decision**: The architectural decision made
- **Rationale**: Why this decision was chosen
- **Consequences**: Both positive and negative outcomes of the decision
- **Alternatives**: Other options that were considered
- **Implementation**: Technical details and examples
- **Status**: Current state of the decision (Draft, Approved, Superseded, etc.)
## Naming Convention
ADRs should follow this naming pattern:
```
NNNN-short-descriptive-title.md
```
Where:
- `NNNN` is a 4-digit sequential number (e.g., 0001, 0002, 0003...)
- `short-descriptive-title` uses kebab-case and briefly describes the decision
- `.md` indicates it's a Markdown file
### Examples:
- `0001-use-standalone-components.md`
- `0002-adopt-ngrx-signals.md`
- `0003-implement-micro-frontend-architecture.md`
- `0004-choose-vitest-over-jest.md`
## Process Guidelines
### 1. When to Create an ADR
Create an ADR when making decisions about:
- **Architecture patterns** (e.g., micro-frontends, monorepo structure)
- **Technology choices** (e.g., testing frameworks, state management)
- **Development practices** (e.g., code organization, build processes)
- **Technical standards** (e.g., coding conventions, performance requirements)
- **Infrastructure decisions** (e.g., deployment strategies, CI/CD processes)
### 2. ADR Lifecycle
```
Draft → Under Review → Approved → [Superseded/Deprecated]
```
- **Draft**: Initial version, being written
- **Under Review**: Shared with team for feedback and discussion
- **Approved**: Team has agreed and decision is implemented
- **Superseded**: Replaced by a newer ADR
- **Deprecated**: No longer applicable but kept for historical reference
### 3. Creation Process
1. **Identify the Need**: Recognize an architectural decision needs documentation
2. **Create from Template**: Copy [TEMPLATE.md](./TEMPLATE.md) to create new ADR
3. **Fill in Content**: Complete all sections with relevant information
4. **Set Status to Draft**: Mark the document as "Draft" initially
5. **Share for Review**: Present to team for discussion and feedback
6. **Iterate**: Update based on team input
7. **Approve**: Once consensus is reached, mark as "Approved"
8. **Implement**: Begin implementation of the architectural decision
### 4. Review Process
- **Author Review**: Self-review for completeness and clarity
- **Peer Review**: Share with relevant team members for technical review
- **Architecture Review**: Present in architecture meetings if significant
- **Final Approval**: Get sign-off from technical leads/architects
## Angular/Nx Specific Considerations
When writing ADRs for this project, consider these Angular/Nx specific aspects:
### Architecture Decisions
- **Library organization** in the monorepo structure
- **Dependency management** between applications and libraries
- **Feature module vs. standalone component** approaches
- **State management patterns** (NgRx, Signals, Services)
- **Routing strategies** for large applications
### Technical Decisions
- **Build optimization** strategies using Nx
- **Testing approaches** for different types of libraries
- **Code sharing patterns** across applications
- **Performance optimization** techniques
- **Bundle splitting** and lazy loading strategies
### Development Workflow
- **Nx executor usage** for custom tasks
- **Generator patterns** for code scaffolding
- **Linting and formatting** configurations
- **CI/CD pipeline** optimizations using Nx affected commands
## Template Usage
### Getting Started
1. Copy the [TEMPLATE.md](./TEMPLATE.md) file
2. Rename it following the naming convention
3. Replace placeholder text with actual content
4. Focus on the "why" not just the "what"
5. Include concrete examples and code snippets
6. Consider both immediate and long-term consequences
### Key Template Sections
- **Decision**: State the architectural decision clearly and concisely
- **Context**: Provide background information and constraints
- **Consequences**: Be honest about both benefits and drawbacks
- **Implementation**: Include practical examples relevant to Angular/Nx
- **Alternatives**: Show you considered other options
## Examples of Good ADRs
Here are some example titles that would make good ADRs for this project:
- **State Management**: "0001-adopt-ngrx-signals-for-component-state.md"
- **Testing Strategy**: "0002-use-angular-testing-utilities-over-spectator.md"
- **Code Organization**: "0003-implement-domain-driven-library-structure.md"
- **Performance**: "0004-implement-lazy-loading-for-feature-modules.md"
- **Build Process**: "0005-use-nx-cloud-for-distributed-task-execution.md"
## Best Practices
### Writing Effective ADRs
1. **Be Concise**: Keep it focused and to the point
2. **Be Specific**: Include concrete examples and implementation details
3. **Be Honest**: Document both pros and cons honestly
4. **Be Timely**: Write ADRs close to when decisions are made
5. **Be Collaborative**: Involve relevant team members in the process
### Maintenance
- **Review Regularly**: Check ADRs during architecture reviews
- **Update Status**: Keep status current as decisions evolve
- **Link Related ADRs**: Reference connected decisions
- **Archive Outdated**: Mark superseded ADRs appropriately
### Code Examples
When including code examples:
- Use actual project syntax and patterns
- Include both TypeScript and template examples where relevant
- Show before/after scenarios for changes
- Reference specific files in the codebase when possible
## Tools and Integration
### Recommended Tools
- **Markdown Editor**: Use any markdown-capable editor
- **Version Control**: All ADRs are tracked in Git
- **Review Process**: Use PR reviews for ADR approval
- **Documentation**: Link ADRs from relevant code comments
### Integration with Development
- Reference ADR numbers in commit messages when implementing decisions
- Include ADR links in PR descriptions for architectural changes
- Update ADRs when decisions need modification
- Use ADRs as reference during code reviews
## Getting Help
### Questions or Issues?
- **Team Discussions**: Bring up in team meetings or Slack
- **Architecture Review**: Present in architecture meetings
- **Documentation**: Update this README if process improvements are needed
### Resources
- [Architecture Decision Records (ADRs) - Michael Nygard](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)
- [ADR GitHub Organization](https://adr.github.io/)
- [Nx Documentation](https://nx.dev/getting-started/intro)
- [Angular Architecture Guide](https://angular.dev/guide/architecture)
---
*This ADR system helps maintain architectural consistency and knowledge sharing across the ISA-Frontend project. Keep it updated and use it regularly for the best results.*

View File

@@ -0,0 +1,138 @@
# ADR NNNN: <short-descriptive-title>
| Field | Value |
|-------|-------|
| Status | Draft / Under Review / Approved / Superseded by ADR NNNN / Deprecated |
| Date | YYYY-MM-DD |
| Owners | <author(s)> |
| Participants | <key reviewers / stakeholders> |
| Related ADRs | NNNN (title), NNNN (title) |
| Tags | architecture, <domain>, <category> |
---
## Summary (Decision in One Sentence)
Concise statement of the architectural decision. Avoid rationale here—just the what.
## Context & Problem Statement
Describe the background and the problem this decision addresses.
- Business drivers / user needs
- Technical constraints (performance, security, scalability, compliance, legacy, regulatory)
- Current pain points / gaps
- Measurable goals / success criteria (e.g. reduce build time by 30%)
### Scope
What is in scope and explicitly out of scope for this decision.
## Decision
State the decision clearly (active voice). Include high-level approach or pattern selection, not implementation detail.
## Rationale
Why this option was selected:
- Alignment with strategic/technical direction
- Trade-offs considered
- Data, benchmarks, experiments, spikes
- Impact on developer experience / velocity
- Long-term maintainability & extensibility
## Alternatives Considered
| Alternative | Summary | Pros | Cons | Reason Not Chosen |
|-------------|---------|------|------|-------------------|
| Option A | | | | |
| Option B | | | | |
| Option C | | | | |
Add deeper detail below if needed:
### Option A <name>
### Option B <name>
### Option C <name>
## Consequences
### Positive
-
### Negative / Risks / Debt Introduced
-
### Neutral / Open Questions
-
## Implementation Plan
High-level rollout strategy. Break into phases if applicable.
1. Phase 0 Spike / Validation
2. Phase 1 Foundation / Infrastructure
3. Phase 2 Incremental Adoption / Migration
4. Phase 3 Hardening / Optimization
5. Phase 4 Decommission Legacy
### Tasks / Workstreams
- Infra / tooling changes
- Library additions (Nx generators, new libs under `libs/<domain>`)
- Refactors / migrations
- Testing strategy updates (Jest → Vitest, Signals adoption, etc.)
- Documentation & onboarding materials
### Acceptance Criteria
List objective criteria to mark implementation complete.
### Rollback Plan
How to revert safely if outcomes are negative.
## Architectural Impact
### Nx / Monorepo Layout
Describe changes to library boundaries, tags, dependency graph, affected projects.
### Module / Library Design
New or modified public APIs (`src/index.ts` changes, path aliases additions to `tsconfig.base.json`).
### State Management
Implications for Signals, NgRx, resource factories, persistence patterns (`withStorage`).
### Runtime & Performance
Bundle size, lazy loading, code splitting, caching, SSR/hydration considerations.
### Security & Compliance
AuthZ/AuthN, token handling, data residency, PII, secure storage.
### Observability & Logging
Logging contexts (`@isa/core/logging`), metrics, tracing hooks.
### DX / Tooling
Generators, lint rules, schematic updates, local dev flow.
## Detailed Design Elements
(Optional deeper technical articulation.)
- Sequence diagrams / component diagrams
- Data flow / async flow
- Error handling strategy
- Concurrency / cancellation (e.g. `rxMethod` + `switchMap` usage)
- Abstractions & extension points
## Code Examples
### Before
```ts
// Previous approach (simplified)
```
### After
```ts
// New approach (simplified)
```
### Migration Snippet
```ts
// Example incremental migration pattern
```
## Open Questions / Follow-Ups
- Unresolved design clarifications
- Dependent ADRs required
- External approvals needed
## Decision Review & Revalidation
When and how this ADR will be re-evaluated (date, trigger conditions, metrics thresholds).
## Status Log
| Date | Change | Author |
|------|--------|--------|
| YYYY-MM-DD | Created (Draft) | |
| YYYY-MM-DD | Approved | |
| YYYY-MM-DD | Superseded by ADR NNNN | |
## References
- Links to spike notes, benchmark results
- External articles, standards, RFCs
- Related code PRs / commits
---
> Document updates MUST reference this ADR number in commit messages: `ADR-NNNN:` prefix.
> Keep this document updated through all lifecycle stages.

View File

@@ -0,0 +1,506 @@
# ADR 0001: Implement `data-access` API Requests
| Field | Value |
|-------|-------|
| Status | Draft |
| Date | 29.09.2025 |
| Owners | Lorenz, Nino |
| Participants | N/A |
| Related ADRs | N/A |
| Tags | architecture, data-access, library, swagger |
---
## Summary (Decision in One Sentence)
Standardize data-access library implementation patterns for API requests using Zod schemas for validation, domain-specific models extending generated DTOs, and service layers that integrate with generated Swagger clients.
## Context & Problem Statement
The ISA Frontend application requires consistent and maintainable patterns for implementing API requests across multiple domain libraries. Current data-access libraries show varying implementation approaches that need standardization.
**Business drivers / user needs:**
- Consistent error handling across all API interactions
- Type-safe request/response handling to prevent runtime errors
- Maintainable code structure for easy onboarding and development
- Reliable validation of API inputs and outputs
**Technical constraints:**
- Must integrate with generated Swagger clients (`@generated/swagger/*`)
- Need to support abort signals for request cancellation
- Require caching and performance optimization capabilities
- Must align with existing logging infrastructure (`@isa/core/logging`)
- Support for domain-specific model extensions beyond generated DTOs
**Current pain points:**
- Inconsistent validation patterns across different data-access libraries
- Mixed approaches to error handling and response processing
- Duplication of common patterns (abort signal handling, response parsing)
- Lack of standardized model extension patterns
**Measurable goals:**
- Standardize API request patterns across all 4+ data-access libraries
- Reduce boilerplate code by 40% through shared utilities
- Improve type safety with comprehensive Zod schema coverage
### Scope
**In scope:**
- Schema validation patterns using Zod
- Model definition standards extending generated DTOs
- Service implementation patterns with generated Swagger clients
- Error handling and response processing standardization
- Integration with common utilities and logging
**Out of scope:**
- Modification of generated Swagger client code
- Changes to backend API contracts
- Authentication/authorization mechanisms
- Caching implementation details (handled by decorators)
## Decision
Implement a three-layer architecture pattern for data-access libraries:
1. **Schema Layer**: Use Zod schemas for input validation and type inference, following the naming convention `<Operation>Schema` with corresponding `<Operation>` and `<Operation>Input` types
2. **Model Layer**: Define domain-specific interfaces that extend generated DTOs, using `EntityContainer<T>` pattern for lazy-loaded relationships
3. **Service Layer**: Create injectable services that integrate generated Swagger clients, implement standardized error handling, and support request cancellation via AbortSignal
All data-access libraries will follow the standard export structure: `models`, `schemas`, `services`, and optionally `stores` and `helpers`.
## Rationale
**Alignment with strategic/technical direction:**
- Leverages existing Zod integration for consistent validation across the application
- Builds upon established generated Swagger client infrastructure
- Aligns with Angular dependency injection patterns and service architecture
- Supports the project's type-safety goals with TypeScript
**Trade-offs considered:**
- **Schema validation overhead**: Zod validation adds minimal runtime cost but provides significant development-time safety
- **Model extension complexity**: Interface extension pattern adds a layer but enables domain-specific enhancements
- **Service layer abstraction**: Additional abstraction over generated clients but enables consistent error handling and logging
**Evidence from current implementation:**
- Analysis of 4 data-access libraries shows successful patterns in `catalogue`, `remission`, `crm`, and `oms`
- `RemissionReturnReceiptService` demonstrates effective integration with logging and error handling
- `EntityContainer<T>` pattern proven effective for lazy-loaded relationships in remission domain
**Developer experience impact:**
- Consistent patterns reduce cognitive load when switching between domains
- Type inference from Zod schemas eliminates manual type definitions
- Standardized error handling reduces debugging time
- Auto-completion and type safety improve development velocity
**Long-term maintainability:**
- Clear separation of concerns between validation, models, and API integration
- Generated client changes don't break domain-specific model extensions
- Consistent logging and error handling simplifies troubleshooting
## Alternatives Considered
| Alternative | Summary | Pros | Cons | Reason Not Chosen |
|-------------|---------|------|------|-------------------|
| Option A | | | | |
| Option B | | | | |
| Option C | | | | |
Add deeper detail below if needed:
### Option A <name>
### Option B <name>
### Option C <name>
## Consequences
### Positive
-
### Negative / Risks / Debt Introduced
-
### Neutral / Open Questions
-
## Implementation Plan
### Phase 0 Analysis & Standards (Completed)
- ✅ Analyzed existing data-access libraries (`catalogue`, `remission`, `crm`, `oms`)
- ✅ Identified common patterns and best practices
- ✅ Documented standard library structure
### Phase 1 Common Utilities Enhancement
- Enhance `@isa/common/data-access` with additional utilities
- Add standardized error types and response handling
- Create reusable operators and decorators
- Add helper functions for common API patterns
### Phase 2 Template & Generator Creation
- Create Nx generator for new data-access libraries
- Develop template files for schemas, models, and services
- Add code snippets and documentation templates
- Create migration guide for existing libraries
### Phase 3 Existing Library Standardization
- Update `catalogue/data-access` to follow complete pattern
- Migrate `crm/data-access` to standard structure
- Ensure `remission/data-access` follows all conventions
- Standardize `oms/data-access` implementation
### Phase 4 New Library Implementation
- Apply patterns to new domain libraries as they're created
- Use Nx generator for consistent setup
- Enforce patterns through code review and linting
### Tasks / Workstreams
**Infrastructure:**
- Update `@isa/common/data-access` with enhanced utilities
- Add ESLint rules for data-access pattern enforcement
- Update `tsconfig.base.json` path mappings as needed
**Library Enhancements:**
- Create Nx generator: `nx g @isa/generators:data-access-lib <domain>`
- Add utility functions to `@isa/common/data-access`
- Enhanced error handling and logging patterns
**Migration Tasks:**
- Standardize schema validation across all libraries
- Ensure consistent model extension patterns
- Align service implementations with logging standards
- Update tests to match new patterns
**Documentation:**
- Create data-access implementation guide
- Update onboarding materials with patterns
- Add code examples to development wiki
- Document generator usage and options
### Acceptance Criteria
- [ ] All data-access libraries follow standardized structure
- [ ] All API requests use Zod schema validation
- [ ] All services implement consistent error handling
- [ ] All services support AbortSignal for cancellation
- [ ] All models extend generated DTOs appropriately
- [ ] Nx generator produces compliant library structure
- [ ] Code review checklist includes data-access patterns
- [ ] Performance benchmarks show no degradation
### Rollback Plan
- Individual library changes can be reverted via Git
- Generated libraries can be recreated with previous patterns
- No breaking changes to existing public APIs
- Gradual migration allows for partial rollback by domain
## Architectural Impact
### Nx / Monorepo Layout
- Data-access libraries follow domain-based organization: `libs/<domain>/data-access/`
- Each library exports standard modules: `models`, `schemas`, `services`
- Dependencies on `@isa/common/data-access` for shared utilities
- Integration with generated Swagger clients via `@generated/swagger/<api-name>`
### Module / Library Design
**Standard public API structure (`src/index.ts`):**
```typescript
export * from './lib/models';
export * from './lib/schemas';
export * from './lib/services';
// Optional: stores, helpers
```
**Path aliases in `tsconfig.base.json`:**
- `@isa/<domain>/data-access` for each domain library
- `@generated/swagger/<api-name>` for generated clients
- `@isa/common/data-access` for shared utilities
### State Management
- Services integrate with NgRx signal stores in feature libraries
- `EntityContainer<T>` pattern supports lazy loading in state management
- Resource factory pattern used for async state management (see remission examples)
- Caching implemented via decorators (`@Cache`, `@InFlight`)
### Runtime & Performance
- Zod schema validation adds minimal runtime overhead
- Generated clients are tree-shakeable
- AbortSignal support enables request cancellation
- Caching decorators reduce redundant API calls
- `firstValueFrom` pattern avoids memory leaks from subscriptions
### Security & Compliance
- All API calls go through generated clients with consistent auth handling
- Input validation via Zod schemas prevents injection attacks
- AbortSignal support enables proper request cleanup
- Logging excludes sensitive data through structured context
### Observability & Logging
- Consistent logging via `@isa/core/logging` with service-level context
- Structured logging with operation context and request metadata
- Error logging includes request details without sensitive data
- Debug logging for development troubleshooting
### DX / Tooling
- Consistent patterns reduce learning curve across domains
- Type inference from Zod schemas eliminates manual type definitions
- Auto-completion from TypeScript interfaces
- Standard error handling patterns
## Detailed Design Elements
### Schema Validation Pattern
**Structure:**
```typescript
// Input validation schema
export const SearchByTermSchema = z.object({
searchTerm: z.string().min(1, 'Search term must not be empty'),
skip: z.number().int().min(0).default(0),
take: z.number().int().min(1).max(100).default(20),
});
// Type inference
export type SearchByTerm = z.infer<typeof SearchByTermSchema>;
export type SearchByTermInput = z.input<typeof SearchByTermSchema>;
```
### Model Extension Pattern
**Generated DTO Extension:**
```typescript
import { ProductDTO } from '@generated/swagger/cat-search-api';
export interface Product extends ProductDTO {
name: string;
contributors: string;
catalogProductNumber: string;
// Domain-specific enhancements
}
```
**Entity Container Pattern:**
```typescript
export interface Return extends ReturnDTO {
id: number;
receipts: EntityContainer<Receipt>[]; // Lazy-loaded relationships
}
```
### Service Implementation Pattern
**Standard service structure:**
```typescript
@Injectable({ providedIn: 'root' })
export class DomainService {
#apiService = inject(GeneratedApiService);
#logger = logger(() => ({ service: 'DomainService' }));
async fetchData(params: InputType, abortSignal?: AbortSignal): Promise<ResultType> {
const validated = ValidationSchema.parse(params);
let req$ = this.#apiService.operation(validated);
if (abortSignal) {
req$ = req$.pipe(takeUntilAborted(abortSignal));
}
const res = await firstValueFrom(req$);
if (res.error) {
this.#logger.error('Operation failed', new Error(res.message));
throw new ResponseArgsError(res);
}
return res.result as ResultType;
}
}
```
### Error Handling Strategy
1. **Input Validation**: Zod schemas validate and transform inputs
2. **API Error Handling**: Check `res.error` from generated clients
3. **Structured Logging**: Log errors with context via `@isa/core/logging`
4. **Error Propagation**: Throw `ResponseArgsError` for consistent handling
### Concurrency & Cancellation
- **AbortSignal Support**: All async operations accept optional AbortSignal
- **RxJS Integration**: Use `takeUntilAborted` operator for cancellation
- **Promise Pattern**: `firstValueFrom` prevents subscription memory leaks
- **Caching**: `@InFlight` decorator prevents duplicate concurrent requests
### Extension Points
- **Custom Decorators**: `@Cache`, `@InFlight`, `@CacheTimeToLive`
- **Schema Transformations**: Zod `.transform()` for data normalization
- **Model Inheritance**: Interface extension for domain-specific properties
- **Service Composition**: Services can depend on other domain services
## Code Examples
### Complete Data-Access Library Structure
```typescript
// libs/domain/data-access/src/lib/schemas/fetch-items.schema.ts
import { z } from 'zod';
export const FetchItemsSchema = z.object({
categoryId: z.string().min(1),
skip: z.number().int().min(0).default(0),
take: z.number().int().min(1).max(100).default(20),
filters: z.record(z.any()).default({}),
});
export type FetchItems = z.infer<typeof FetchItemsSchema>;
export type FetchItemsInput = z.input<typeof FetchItemsSchema>;
// libs/domain/data-access/src/lib/models/item.ts
import { ItemDTO } from '@generated/swagger/domain-api';
import { EntityContainer } from '@isa/common/data-access';
import { Category } from './category';
export interface Item extends ItemDTO {
id: number;
displayName: string;
category: EntityContainer<Category>;
// Domain-specific enhancements
isAvailable: boolean;
formattedPrice: string;
}
// libs/domain/data-access/src/lib/services/item.service.ts
import { inject, Injectable } from '@angular/core';
import { ItemService as GeneratedItemService } from '@generated/swagger/domain-api';
import { firstValueFrom } from 'rxjs';
import { takeUntilAborted, ResponseArgsError } from '@isa/common/data-access';
import { logger } from '@isa/core/logging';
import { FetchItemsInput, FetchItemsSchema } from '../schemas';
import { Item } from '../models';
@Injectable({ providedIn: 'root' })
export class ItemService {
#itemService = inject(GeneratedItemService);
#logger = logger(() => ({ service: 'ItemService' }));
async fetchItems(
params: FetchItemsInput,
abortSignal?: AbortSignal
): Promise<Item[]> {
this.#logger.debug('Fetching items', () => ({ params }));
const { categoryId, skip, take, filters } = FetchItemsSchema.parse(params);
let req$ = this.#itemService.getItems({
categoryId,
queryToken: { skip, take, filter: filters }
});
if (abortSignal) {
req$ = req$.pipe(takeUntilAborted(abortSignal));
}
const res = await firstValueFrom(req$);
if (res.error) {
this.#logger.error('Failed to fetch items', new Error(res.message));
throw new ResponseArgsError(res);
}
this.#logger.info('Successfully fetched items', () => ({
count: res.result?.length || 0
}));
return res.result as Item[];
}
}
// libs/domain/data-access/src/index.ts
export * from './lib/models';
export * from './lib/schemas';
export * from './lib/services';
```
### Usage in Feature Components
```typescript
// feature component using the data-access library
import { Component, inject, signal } from '@angular/core';
import { ItemService, Item, FetchItemsInput } from '@isa/domain/data-access';
@Component({
selector: 'app-item-list',
template: `
@if (loading()) {
<div>Loading...</div>
} @else {
@for (item of items(); track item.id) {
<div>{{ item.displayName }}</div>
}
}
`
})
export class ItemListComponent {
#itemService = inject(ItemService);
items = signal<Item[]>([]);
loading = signal(false);
async loadItems(categoryId: string) {
this.loading.set(true);
try {
const params: FetchItemsInput = {
categoryId,
take: 50,
filters: { active: true }
};
const items = await this.#itemService.fetchItems(params);
this.items.set(items);
} catch (error) {
console.error('Failed to load items', error);
} finally {
this.loading.set(false);
}
}
}
```
### Migration Pattern for Existing Services
```typescript
// Before: Direct HTTP client usage
@Injectable()
export class LegacyItemService {
constructor(private http: HttpClient) {}
getItems(categoryId: string): Observable<any> {
return this.http.get(`/api/items?category=${categoryId}`);
}
}
// After: Standardized data-access pattern
@Injectable({ providedIn: 'root' })
export class ItemService {
#itemService = inject(GeneratedItemService);
#logger = logger(() => ({ service: 'ItemService' }));
async fetchItems(params: FetchItemsInput, abortSignal?: AbortSignal): Promise<Item[]> {
const validated = FetchItemsSchema.parse(params);
// ... standard implementation pattern
}
}
```
## Open Questions / Follow-Ups
- Unresolved design clarifications
- Dependent ADRs required
- External approvals needed
## Decision Review & Revalidation
When and how this ADR will be re-evaluated (date, trigger conditions, metrics thresholds).
## Status Log
| Date | Change | Author |
|------|--------|--------|
| 2025-09-29 | Created (Draft) | Lorenz, Nino |
| 2025-09-25 | Analysis completed, comprehensive patterns documented | AI Assistant |
## References
**Existing Implementation Examples:**
- `libs/catalogue/data-access` - Basic schema and service patterns
- `libs/remission/data-access` - Advanced patterns with EntityContainer and stores
- `libs/common/data-access` - Shared utilities and response types
- `generated/swagger/` - Generated API clients integration
**Key Dependencies:**
- [Zod](https://github.com/colinhacks/zod) - Schema validation library
- [ng-swagger-gen](https://github.com/cyclosproject/ng-swagger-gen) - OpenAPI client generation
- `@isa/core/logging` - Structured logging infrastructure
- `@isa/common/data-access` - Shared utilities and types
**Related Documentation:**
- ISA Frontend Copilot Instructions - Data-access patterns
- Tech Stack Documentation - Architecture overview
- Code Style Guidelines - TypeScript and Angular patterns
---
> Document updates MUST reference this ADR number in commit messages: `ADR-NNNN:` prefix.
> Keep this document updated through all lifecycle stages.