diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 000000000..91aebecf5 --- /dev/null +++ b/docs/architecture/README.md @@ -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.* diff --git a/docs/architecture/TEMPLATE.md b/docs/architecture/TEMPLATE.md new file mode 100644 index 000000000..1e84663c2 --- /dev/null +++ b/docs/architecture/TEMPLATE.md @@ -0,0 +1,138 @@ +# ADR NNNN: + +| Field | Value | +|-------|-------| +| Status | Draft / Under Review / Approved / Superseded by ADR NNNN / Deprecated | +| Date | YYYY-MM-DD | +| Owners | | +| Participants | | +| Related ADRs | NNNN (title), NNNN (title) | +| Tags | architecture, , | + +--- +## 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 – +### Option B – +### Option C – + +## 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/`) +- 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. diff --git a/docs/architecture/adr/0001-implement-data-access-api-requests.md b/docs/architecture/adr/0001-implement-data-access-api-requests.md new file mode 100644 index 000000000..c7ada9570 --- /dev/null +++ b/docs/architecture/adr/0001-implement-data-access-api-requests.md @@ -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 `Schema` with corresponding `` and `Input` types +2. **Model Layer**: Define domain-specific interfaces that extend generated DTOs, using `EntityContainer` 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` 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 – +### Option B – +### Option C – + +## 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 ` +- 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//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/` + +### 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//data-access` for each domain library +- `@generated/swagger/` for generated clients +- `@isa/common/data-access` for shared utilities + +### State Management +- Services integrate with NgRx signal stores in feature libraries +- `EntityContainer` 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; +export type SearchByTermInput = z.input; +``` + +### 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[]; // 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 { + 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; +export type FetchItemsInput = z.input; + +// 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; + // 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 { + 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()) { +
Loading...
+ } @else { + @for (item of items(); track item.id) { +
{{ item.displayName }}
+ } + } + ` +}) +export class ItemListComponent { + #itemService = inject(ItemService); + + items = signal([]); + 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 { + 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 { + 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.