fix: Gitea Traefik routing and connection pool optimization
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled

- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
This commit is contained in:
2025-11-09 14:46:15 +01:00
parent 85c369e846
commit 36ef2a1e2c
1366 changed files with 104925 additions and 28719 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,731 @@
# Markdown Files Analysis - Custom PHP Framework
**Generated:** $(date)
**Total Project Files:** 1579 (including dependencies)
**Relevant Files:** 513 (excluding node_modules, vendor, .git)
---
## Executive Summary
This analysis covers all markdown files in the Custom PHP Framework project, excluding third-party dependencies. The goal is to reorganize documentation from AI-specific `/docs/claude/` to general `/docs/` structure.
### Key Statistics
- **Total Markdown Files:** 513
- **Documentation Files:** ~100 (estimated, in /docs/)
- **Source Code Docs:** ~50 (README files in /src/)
- **Test Documentation:** ~20 (test strategy, examples)
- **Configuration Docs:** ~10 (deployment, docker, ansible)
- **Dependencies:** 1066 (node_modules + vendor - excluded)
---
## File Distribution by Directory
```
63 ./docs/claude
57 ./docs
48 ./docs/deployment
17 ./src/Framework/View/Processors/docs
15 ./backups/docs-backup-20250731125004
14 ./.claude/agents
13 ./docs/livecomponents
12 ./.gitea/workflows
11 ./docs/planning
9 .
7 ./docs/guides
6 ./src/Framework/LiveComponents/docs
6 ./deployment/docs/tests
6 ./backups/docs-backup-20250731125004/framework
5 ./tests/e2e/livecomponents
5 ./resources/js/docs
5 ./deployment/wireguard
5 ./deployment/docs/status
5 ./deployment/docs/guides
5 ./backups/docs-backup-20250731125004/framework/analytics
4 ./src/Framework/LiveComponents
4 ./docs/todo
4 ./docs/contributing
4 ./docs/components/waf
4 ./docs/components/security
4 ./docs/components/cryptography
4 ./docs/components/auth
4 ./backups/docs-backup-20250731125004/design-system
3 ./src/Framework/ReflectionLegacy
3 ./docs/roadmap
```
---
## Detailed File Listing by Category
### 1. Documentation Directory (/docs/)
- `./docs/admin-design-system.md` (479 lines)
- `./docs/ADMIN-FORM-FIELDS-DESIGN.md` (440 lines)
- `./docs/ADMIN-FORM-FIELDS-USAGE.md` (491 lines)
- `./docs/api/index.md` (838 lines)
- `./docs/api.md` (8 lines)
- `./docs/api-versioning-examples.md` (294 lines)
- `./docs/architecture/components.md` (528 lines)
- `./docs/ARCHITECTURE_IMPROVEMENTS.md` (1981 lines)
- `./docs/architecture/overview.md` (226 lines)
- `./docs/architecture/patterns.md` (1137 lines)
- `./docs/batch-api-examples.md` (236 lines)
- `./docs/cache-warming.md` (699 lines)
- `./docs/claude/animationsystem.md` (585 lines)
- `./docs/claude/architecture.md` (189 lines)
- `./docs/claude/async-components.md` (26 lines)
- `./docs/claude/chips-cookies.md` (465 lines)
- `./docs/claude/common-workflows.md` (1259 lines)
- `./docs/claude/configuration-best-practices.md` (297 lines)
- `./docs/claude/console-commands.md` (30 lines)
- `./docs/claude/curl-oop-api.md` (996 lines)
- `./docs/claude/database-patterns.md` (1526 lines)
- `./docs/claude/deployment-architecture.md` (777 lines)
- `./docs/claude/development-commands.md` (157 lines)
- `./docs/claude/error-handling.md` (644 lines)
- `./docs/claude/event-system.md` (963 lines)
- `./docs/claude/examples/migrations/SafeVsUnsafeMigrations.md` (420 lines)
- `./docs/claude/exception-system-advanced-features.md` (754 lines)
- `./docs/claude/filesystem-patterns.md` (965 lines)
- `./docs/claude/framework-personas.md` (766 lines)
- `./docs/claude/framework-refactoring-recommendations.md` (748 lines)
- `./docs/claude/guidelines.md` (882 lines)
- `./docs/claude/livecomponent-file-uploads.md` (893 lines)
- `./docs/claude/livecomponent-formbuilder-usage.md` (458 lines)
- `./docs/claude/livecomponent-lazy-loading.md` (681 lines)
- `./docs/claude/livecomponent-lifecycle-hooks.md` (572 lines)
- `./docs/claude/livecomponent-nested-components.md` (717 lines)
- `./docs/claude/livecomponents-best-practices.md` (461 lines)
- `./docs/claude/livecomponents-caching-system.md` (683 lines)
- `./docs/claude/livecomponents-dom-badges.md` (236 lines)
- `./docs/claude/livecomponent-security.md` (223 lines)
- `./docs/claude/livecomponents-implementation-plan.md` (699 lines)
- `./docs/claude/livecomponents-lazy-loading.md` (717 lines)
- `./docs/claude/livecomponent-slot-system.md` (1127 lines)
- `./docs/claude/livecomponents-monitoring-debugging.md` (701 lines)
- `./docs/claude/livecomponents-observability.md` (540 lines)
- `./docs/claude/livecomponents-performance-optimizations.md` (725 lines)
- `./docs/claude/livecomponents-playground.md` (1108 lines)
- `./docs/claude/livecomponents-roadmap.md` (1027 lines)
- `./docs/claude/livecomponents-system.md` (552 lines)
- `./docs/claude/livecomponents-test-harness.md` (504 lines)
- `./docs/claude/magiclinks-system.md` (807 lines)
- `./docs/claude/mcp-integration.md` (260 lines)
- `./docs/claude/migration-system-quick-reference.md` (202 lines)
- `./docs/claude/ml-framework-architecture.md` (593 lines)
- `./docs/claude/naming-conventions.md` (832 lines)
- `./docs/claude/performance-monitoring.md` (30 lines)
- `./docs/claude/performance-profiling.md` (857 lines)
- `./docs/claude/php85-framework-integration.md` (550 lines)
- `./docs/claude/posix-system.md` (1316 lines)
- `./docs/claude/postgresql-features.md` (1127 lines)
- `./docs/claude/queue-system.md` (1135 lines)
- `./docs/claude/route-authorization.md` (291 lines)
- `./docs/claude/routing-value-objects.md` (305 lines)
- `./docs/claude/scheduler-queue-pipeline.md` (458 lines)
- `./docs/claude/scheduler-queue-pipeline-persona.md` (273 lines)
- `./docs/claude/security-patterns.md` (1135 lines)
- `./docs/claude/sockets-module.md` (671 lines)
- `./docs/claude/sse-integration-guide.md` (978 lines)
- `./docs/claude/sse-system.md` (1068 lines)
- `./docs/claude/structured-logging.md` (577 lines)
- `./docs/claude/troubleshooting.md` (1074 lines)
- `./docs/claude/typed-string-system.md` (1141 lines)
- `./docs/claude/view-caching-system.md` (716 lines)
- `./docs/claude/view-refactoring-plan.md` (614 lines)
- `./docs/claude/xcomponent-processor.md` (764 lines)
- `./docs/claude/x-component-syntax.md` (335 lines)
- `./docs/components/analytics/configuration.md` (477 lines)
- `./docs/components/analytics/examples.md` (760 lines)
- `./docs/components/analytics/index.md` (507 lines)
- `./docs/components/auth/configuration.md` (429 lines)
- `./docs/components/auth/examples.md` (796 lines)
- `./docs/components/auth/index.md` (309 lines)
- `./docs/components/auth/security.md` (903 lines)
- `./docs/components/cryptography/configuration.md` (396 lines)
- `./docs/components/cryptography/examples.md` (702 lines)
- `./docs/components/cryptography/index.md` (364 lines)
- `./docs/components/cryptography/security.md` (727 lines)
- `./docs/components/security/csrf-protection.md` (417 lines)
- `./docs/components/security/index.md` (363 lines)
- `./docs/components/security/request-signing.md` (410 lines)
- `./docs/components/security/security-headers.md` (382 lines)
- `./docs/components/validation/examples.md` (424 lines)
- `./docs/components/validation/index.md` (338 lines)
- `./docs/components/validation/rules.md` (451 lines)
- `./docs/components/waf/configuration.md` (279 lines)
- `./docs/components/waf/feedback.md` (280 lines)
- `./docs/components/waf/index.md` (135 lines)
- `./docs/components/waf/machine-learning.md` (252 lines)
- `./docs/console-best-practices.md` (486 lines)
- `./docs/console-dialog-mode.md` (472 lines)
- `./docs/console-optional-parameters.md` (422 lines)
- `./docs/contributing/code-style.md` (598 lines)
- `./docs/contributing/documentation.md` (345 lines)
- `./docs/contributing/git-hooks.md` (151 lines)
- `./docs/contributing/pull-requests.md` (334 lines)
- `./docs/database-migration-fix.md` (78 lines)
- `./docs/database-module-migration-analysis.md` (413 lines)
- `./docs/database/new-features.md` (329 lines)
- `./docs/DefaultImplementation-Attribute.md` (447 lines)
- `./docs/dependency-scanning.md` (401 lines)
- `./docs/deployment/ANSIBLE_DEPLOYMENT.md` (969 lines)
- `./docs/deployment/AUTOSSH-SETUP-COMPLETED.md` (243 lines)
- `./docs/deployment/AUTOSSH-SETUP.md` (428 lines)
- `./docs/deployment/cache-configuration.md` (244 lines)
- `./docs/deployment/cache-permissions-quick-fix.md` (74 lines)
- `./docs/deployment/database-migration-strategy.md` (775 lines)
- `./docs/deployment/deployment-automation.md` (816 lines)
- `./docs/deployment/env-production-template.md` (407 lines)
- `./docs/deployment/gitea-secrets-setup.md` (297 lines)
- `./docs/deployment/GRAFANA-VPN-ACCESS.md` (108 lines)
- `./docs/deployment/GRAFANA-VPN-NEXT-STEPS.md` (125 lines)
- `./docs/deployment/GRAFANA-VPN-SECURITY-PLAN.md` (149 lines)
- `./docs/deployment/local-secrets-unification-plan.md` (470 lines)
- `./docs/deployment/local-stack-restructure-plan.md` (359 lines)
- `./docs/deployment/logging-configuration.md` (715 lines)
- `./docs/deployment/production-compose-consolidation-plan.md` (262 lines)
- `./docs/deployment/production-logging.md` (601 lines)
- `./docs/deployment/production-prerequisites.md` (340 lines)
- `./docs/deployment/PRODUCTION-SECURITY-UPDATES.md` (133 lines)
- `./docs/deployment/README.md` (67 lines)
- `./docs/deployment/secrets-management.md` (614 lines)
- `./docs/deployment/shared-postgres-override-plan.md` (303 lines)
- `./docs/deployment/SSH-MAKEFILE-COMMANDS.md` (319 lines)
- `./docs/deployment/SSL-PRODUCTION-SETUP.md` (194 lines)
- `./docs/deployment/ssl-setup.md` (540 lines)
- `./docs/deployment/staging-database-connection-analysis.md` (185 lines)
- `./docs/deployment/staging-postgres-connection-plan.md` (209 lines)
- `./docs/deployment/test-registry-credentials.md` (197 lines)
- `./docs/deployment/VPN-ROUTING-CLIENT-CHECK.md` (195 lines)
- `./docs/deployment/VPN-ROUTING-FINAL-FIX.md` (91 lines)
- `./docs/deployment/VPN-ROUTING-FIX-DETAILED.md` (100 lines)
- `./docs/deployment/VPN-ROUTING-FIX-GUIDE.md` (143 lines)
- `./docs/deployment/VPN-ROUTING-FIX.md` (120 lines)
- `./docs/deployment/VPN-ROUTING-PROBLEM-ANALYSIS.md` (120 lines)
- `./docs/deployment/WIREGUARD-DNS-FIX-IMPLEMENTED.md` (283 lines)
- `./docs/deployment/WIREGUARD-FUTURE-SECURITY.md` (243 lines)
- `./docs/deployment/WIREGUARD-IMPLEMENTATION-PLAN.md` (1175 lines)
- `./docs/deployment/WIREGUARD-NEW-CONFIG-READY.md` (123 lines)
- `./docs/deployment/WIREGUARD-RECREATE-AND-TEST.md` (176 lines)
- `./docs/deployment/WIREGUARD-SETUP.md` (595 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-CONFIG-EXAMPLE.md` (48 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-DNS-FIX.md` (141 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-DNS-PRIORITY-FIX.md` (108 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-FIREWALL-CHECK.md` (186 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-INTERFACE-METRIC-FIX.md` (63 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-ROUTE-FIX.md` (103 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-ROUTE-GATEWAY-FIX.md` (176 lines)
- `./docs/deployment/WIREGUARD-WINDOWS-ROUTING-FINAL-ANALYSIS.md` (109 lines)
- `./docs/design-token-system.md` (374 lines)
- `./docs/error-handler-enhancements.md` (615 lines)
- `./docs/ERROR-HANDLING-AUDIT-REPORT.md` (708 lines)
- `./docs/ERROR-HANDLING-MIGRATION-PLAN.md` (3319 lines)
- `./docs/ERROR-HANDLING-UNIFIED-ARCHITECTURE.md` (1766 lines)
- `./docs/ERROR-RENDERER-IMPROVEMENTS-PLAN.md` (274 lines)
- `./docs/ERROR-RENDERER-REFACTORING-PLAN.md` (199 lines)
- `./docs/examples/poll-system-usage.md` (609 lines)
- `./docs/exception-hierarchy-pattern.md` (684 lines)
- `./docs/exception-migration-guide.md` (1132 lines)
- `./docs/FILECACHE_PERMISSION_FIX_PLAN.md` (217 lines)
- `./docs/FILEPERMISSION_EXCEPTION_IMPROVEMENT_PLAN.md` (226 lines)
- `./docs/FORPROCESSOR-FIX-SUMMARY.md` (190 lines)
- `./docs/FORPROCESSOR-ISSUE-ANALYSIS.md` (106 lines)
- `./docs/FRAMEWORK-IMPROVEMENT-PROPOSALS.md` (591 lines)
- `./docs/FRAMEWORK_IMPROVEMENTS_ROADMAP.md` (173 lines)
- `./docs/getting-started/configuration.md` (214 lines)
- `./docs/getting-started/first-steps.md` (327 lines)
- `./docs/getting-started/installation.md` (108 lines)
- `./docs/gitea-actions-setup.md` (383 lines)
- `./docs/graphql-examples.md` (386 lines)
- `./docs/guides/controllers.md` (727 lines)
- `./docs/guides/README-image-upload.md` (128 lines)
- `./docs/guides/README-static-site.md` (118 lines)
- `./docs/guides/README-websocket.md` (118 lines)
- `./docs/guides/routing.md` (370 lines)
- `./docs/guides/security.md` (585 lines)
- `./docs/guides/validation.md` (539 lines)
- `./docs/implementations/queue-job-anomaly-detection.md` (634 lines)
- `./docs/job-dashboard.md` (733 lines)
- `./docs/livecomponents/01-getting-started.md` (520 lines)
- `./docs/livecomponents/advanced-features.md` (1027 lines)
- `./docs/livecomponents/api-reference.md` (1331 lines)
- `./docs/livecomponents/attributes-reference.md` (1380 lines)
- `./docs/livecomponents/best-practices.md` (1014 lines)
- `./docs/livecomponents/events-reference.md` (1354 lines)
- `./docs/livecomponents/faq.md` (864 lines)
- `./docs/livecomponents/LIVECOMPONENTS-COMPLETE-SUMMARY.md` (681 lines)
- `./docs/livecomponents/performance-guide.md` (1003 lines)
- `./docs/livecomponents/PHASE-5-COMPLETION.md` (597 lines)
- `./docs/livecomponents/README.md` (257 lines)
- `./docs/livecomponents/security-guide.md` (691 lines)
- `./docs/livecomponents/troubleshooting.md` (978 lines)
- `./docs/livecomponents-type-safety-refactoring.md` (400 lines)
- `./docs/logging/best-practices.md` (837 lines)
- `./docs/logging/docker-json-logging.md` (373 lines)
- `./docs/logging/log-health-check-command.md` (162 lines)
- `./docs/logging-module.md` (185 lines)
- `./docs/Makefile.md` (66 lines)
- `./docs/middleware-robustness.md` (130 lines)
- `./docs/migration/ErrorHandling-to-ExceptionHandling-Strategy.md` (798 lines)
- `./docs/ml-model-management-deployment.md` (807 lines)
- `./docs/ml-model-management.md` (872 lines)
- `./docs/next-steps.md` (67 lines)
- `./docs/n-plus-one-detection.md` (749 lines)
- `./docs/performance/filesystem-optimization-analysis.md` (284 lines)
- `./docs/performance/filesystem-phase1-optimizations-implemented.md` (367 lines)
- `./docs/performance/index-optimization.md` (559 lines)
- `./docs/PERMISSIONS.md` (226 lines)
- `./docs/plan.md` (252 lines)
- `./docs/planning/ADMIN_AUTH_SECURITY_ENHANCEMENT.md` (140 lines)
- `./docs/planning/CURRENT_SPRINT.md` (178 lines)
- `./docs/planning/docs-implementation-plan.md` (163 lines)
- `./docs/planning/docs-replacement-recommendation.md` (137 lines)
- `./docs/planning/documentation-update-proposal.md` (138 lines)
- `./docs/planning/ML-WAF-Behavioral-Analysis-Implementation-Summary.md` (565 lines)
- `./docs/planning/N+1-Detection-ML-Implementation-Summary.md` (263 lines)
- `./docs/planning/N+1-Detection-ML-Integration-Summary.md` (402 lines)
- `./docs/planning/N+1-Detection-ML-Next-Steps.md` (1154 lines)
- `./docs/planning/SECURITY_AUDIT_REPORT.md` (1059 lines)
- `./docs/planning/TODO.md` (425 lines)
- `./docs/PRESAVE-USAGE-GUIDE.md` (458 lines)
- `./docs/quality/code-quality-scanner.md` (112 lines)
- `./docs/queue-deployment.md` (631 lines)
- `./docs/README.md` (68 lines)
- `./docs/REDIS_ACL_EXPLANATION.md` (388 lines)
- `./docs/REDIS_AUTHENTICATION_ANALYSIS.md` (364 lines)
- `./docs/refactoring/mcp-module-refactoring-plan.md` (346 lines)
- `./docs/refactoring/phase-1-completion-report.md` (213 lines)
- `./docs/refactoring/phase-2-completion-report.md` (324 lines)
- `./docs/roadmap/features.md` (83 lines)
- `./docs/roadmap/milestones.md` (289 lines)
- `./docs/roadmap/tasks.md` (138 lines)
- `./docs/search-api-examples.md` (471 lines)
- `./docs/search-external-mapping-examples.md` (255 lines)
- `./docs/spa-router-backend-integration.md` (125 lines)
- `./docs/sqlstate-integration-design.md` (777 lines)
- `./docs/SSL_DEPLOYMENT.md` (371 lines)
- `./docs/tasks.md` (153 lines)
- `./docs/TEMPLATE-SYSTEM-ANALYSIS.md` (386 lines)
- `./docs/todo/css-generation-system.md` (293 lines)
- `./docs/todo/design-system-improvements.md` (263 lines)
- `./docs/todo/design-token-system-future-features.md` (318 lines)
- `./docs/todo/README.md` (68 lines)
- `./docs/troubleshooting/AUTOLOADER_WORKAROUND.md` (67 lines)
- `./docs/vault-system.md` (401 lines)
- `./docs/whatsapp-notification-channel.md` (438 lines)
### 2. Claude-Specific Documentation (/docs/claude/)
- `./docs/claude/animationsystem.md` (585 lines)
- `./docs/claude/architecture.md` (189 lines)
- `./docs/claude/async-components.md` (26 lines)
- `./docs/claude/chips-cookies.md` (465 lines)
- `./docs/claude/common-workflows.md` (1259 lines)
- `./docs/claude/configuration-best-practices.md` (297 lines)
- `./docs/claude/console-commands.md` (30 lines)
- `./docs/claude/curl-oop-api.md` (996 lines)
- `./docs/claude/database-patterns.md` (1526 lines)
- `./docs/claude/deployment-architecture.md` (777 lines)
- `./docs/claude/development-commands.md` (157 lines)
- `./docs/claude/error-handling.md` (644 lines)
- `./docs/claude/event-system.md` (963 lines)
- `./docs/claude/examples/migrations/SafeVsUnsafeMigrations.md` (420 lines)
- `./docs/claude/exception-system-advanced-features.md` (754 lines)
- `./docs/claude/filesystem-patterns.md` (965 lines)
- `./docs/claude/framework-personas.md` (766 lines)
- `./docs/claude/framework-refactoring-recommendations.md` (748 lines)
- `./docs/claude/guidelines.md` (882 lines)
- `./docs/claude/livecomponent-file-uploads.md` (893 lines)
- `./docs/claude/livecomponent-formbuilder-usage.md` (458 lines)
- `./docs/claude/livecomponent-lazy-loading.md` (681 lines)
- `./docs/claude/livecomponent-lifecycle-hooks.md` (572 lines)
- `./docs/claude/livecomponent-nested-components.md` (717 lines)
- `./docs/claude/livecomponents-best-practices.md` (461 lines)
- `./docs/claude/livecomponents-caching-system.md` (683 lines)
- `./docs/claude/livecomponents-dom-badges.md` (236 lines)
- `./docs/claude/livecomponent-security.md` (223 lines)
- `./docs/claude/livecomponents-implementation-plan.md` (699 lines)
- `./docs/claude/livecomponents-lazy-loading.md` (717 lines)
- `./docs/claude/livecomponent-slot-system.md` (1127 lines)
- `./docs/claude/livecomponents-monitoring-debugging.md` (701 lines)
- `./docs/claude/livecomponents-observability.md` (540 lines)
- `./docs/claude/livecomponents-performance-optimizations.md` (725 lines)
- `./docs/claude/livecomponents-playground.md` (1108 lines)
- `./docs/claude/livecomponents-roadmap.md` (1027 lines)
- `./docs/claude/livecomponents-system.md` (552 lines)
- `./docs/claude/livecomponents-test-harness.md` (504 lines)
- `./docs/claude/magiclinks-system.md` (807 lines)
- `./docs/claude/mcp-integration.md` (260 lines)
- `./docs/claude/migration-system-quick-reference.md` (202 lines)
- `./docs/claude/ml-framework-architecture.md` (593 lines)
- `./docs/claude/naming-conventions.md` (832 lines)
- `./docs/claude/performance-monitoring.md` (30 lines)
- `./docs/claude/performance-profiling.md` (857 lines)
- `./docs/claude/php85-framework-integration.md` (550 lines)
- `./docs/claude/posix-system.md` (1316 lines)
- `./docs/claude/postgresql-features.md` (1127 lines)
- `./docs/claude/queue-system.md` (1135 lines)
- `./docs/claude/route-authorization.md` (291 lines)
- `./docs/claude/routing-value-objects.md` (305 lines)
- `./docs/claude/scheduler-queue-pipeline.md` (458 lines)
- `./docs/claude/scheduler-queue-pipeline-persona.md` (273 lines)
- `./docs/claude/security-patterns.md` (1135 lines)
- `./docs/claude/sockets-module.md` (671 lines)
- `./docs/claude/sse-integration-guide.md` (978 lines)
- `./docs/claude/sse-system.md` (1068 lines)
- `./docs/claude/structured-logging.md` (577 lines)
- `./docs/claude/troubleshooting.md` (1074 lines)
- `./docs/claude/typed-string-system.md` (1141 lines)
- `./docs/claude/view-caching-system.md` (716 lines)
- `./docs/claude/view-refactoring-plan.md` (614 lines)
- `./docs/claude/xcomponent-processor.md` (764 lines)
- `./docs/claude/x-component-syntax.md` (335 lines)
### 3. Root Directory Documentation
- `./AGENTS.md` (432 lines)
- `./CLAUDE.md` (292 lines)
- `./CLEANUP_PLAN.md` (186 lines)
- `./DEPLOYMENT_FIX.md` (22 lines)
- `./ENV_SETUP.md` (266 lines)
- `./LIVECOMPONENTS_TEST.md` (160 lines)
- `./README.md` (322 lines)
- `./SRC_STRUCTURE_IMPROVEMENTS.md` (368 lines)
- `./todo.md` (585 lines)
### 4. Source Code Documentation
- `./src/Application/Controllers/Test/README.md` (188 lines)
- `./src/Application/LiveComponents/UserRegistration/README.md` (213 lines)
- `./src/Domain/Asset/README.md` (526 lines)
- `./src/Domain/Cms/README.md` (193 lines)
- `./src/Domain/Media/README.md` (92 lines)
- `./src/Domain/Meta/README.md` (18 lines)
- `./src/Domain/PreSave/README.md` (629 lines)
- `./src/Framework/Admin/README.md` (691 lines)
- `./src/Framework/Analytics/README.md` (342 lines)
- `./src/Framework/AsyncExamples/README.md` (58 lines)
- `./src/Framework/Cache/README.md` (338 lines)
- `./src/Framework/CircuitBreaker/README.md` (210 lines)
- `./src/Framework/Console/README.md` (131 lines)
- `./src/Framework/Core/DOKUMENTATION.md` (45 lines)
- `./src/Framework/Core/ImplementationLocator.md` (17 lines)
- `./src/Framework/Core/ValueObjects/README.md` (334 lines)
- `./src/Framework/Database/Example/README.md` (69 lines)
- `./src/Framework/Database/README.md` (21 lines)
- `./src/Framework/Database/TODO.md` (92 lines)
- `./src/Framework/DDoS/README.md` (133 lines)
- `./src/Framework/DDoS/REFACTORING-SUMMARY.md` (130 lines)
- `./src/Framework/Debug/readme.md` (104 lines)
- `./src/Framework/DI/DOKUMENTATION.md` (90 lines)
- `./src/Framework/Discovery/README.md` (184 lines)
- `./src/Framework/Display/README.md` (583 lines)
- `./src/Framework/ErrorBoundaries/Async/README.md` (265 lines)
- `./src/Framework/ErrorBoundaries/Middleware/README.md` (222 lines)
- `./src/Framework/EventSourcing/Projections/README.md` (394 lines)
- `./src/Framework/EventSourcing/Replay/README.md` (1035 lines)
- `./src/Framework/EventSourcing/Sagas/README.md` (863 lines)
- `./src/Framework/EventSourcing/Snapshots/README.md` (703 lines)
- `./src/Framework/Exception/InErrorHandler.md` (22 lines)
- `./src/Framework/Filesystem/README.md` (68 lines)
- `./src/Framework/Http/DOKUMENTATION.md` (92 lines)
- `./src/Framework/Http/Middlewares/REFACTORING-SUMMARY.md` (144 lines)
- `./src/Framework/Http/Url.php85/README.md` (373 lines)
- `./src/Framework/Http/Url/README.md` (373 lines)
- `./src/Framework/LiveComponents/Cache/README.md` (352 lines)
- `./src/Framework/LiveComponents/docs/API-REFERENCE.md` (1369 lines)
- `./src/Framework/LiveComponents/docs/COMPONENT-CREATION-GUIDE.md` (1114 lines)
- `./src/Framework/LiveComponents/docs/DEVTOOLS-DEBUGGING-GUIDE.md` (1163 lines)
- `./src/Framework/LiveComponents/docs/PERFORMANCE-GUIDE.md` (1023 lines)
- `./src/Framework/LiveComponents/docs/SECURITY-GUIDE.md` (1073 lines)
- `./src/Framework/LiveComponents/docs/UPLOAD-GUIDE.md` (953 lines)
- `./src/Framework/LiveComponents/ERROR-RECOVERY.md` (615 lines)
- `./src/Framework/LiveComponents/MEMORY-MANAGEMENT.md` (264 lines)
- `./src/Framework/LiveComponents/README.md` (75 lines)
- `./src/Framework/LiveComponents/TODO.md` (1216 lines)
- `./src/Framework/Mcp/README.md` (224 lines)
- `./src/Framework/Mcp/Tools/Categories/Analysis/README.md` (19 lines)
- `./src/Framework/Mcp/Tools/Categories/Database/README.md` (37 lines)
- `./src/Framework/Mcp/Tools/Categories/Development/README.md` (30 lines)
- `./src/Framework/Mcp/Tools/Categories/Performance/README.md` (36 lines)
- `./src/Framework/Mcp/Tools/Categories/README.md` (70 lines)
- `./src/Framework/Mcp/Tools/Categories/Security/README.md` (51 lines)
- `./src/Framework/Mcp/Tools/Categories/System/README.md` (51 lines)
- `./src/Framework/Notification/Channels/Telegram/Webhook/README.md` (198 lines)
- `./src/Framework/Notification/Media/README.md` (497 lines)
- `./src/Framework/Notification/README.md` (440 lines)
- `./src/Framework/Notification/Templates/README.md` (524 lines)
- `./src/Framework/OAuth/README.md` (539 lines)
- `./src/Framework/Performance/ARCHITECTURE.md` (234 lines)
- `./src/Framework/Performance/README.md` (369 lines)
- `./src/Framework/Quality/PHPStan/Rules/Naming/README.md` (238 lines)
- `./src/Framework/RateLimit/MIGRATION.md` (337 lines)
- `./src/Framework/ReflectionLegacy/EVALUATION.md` (191 lines)
- `./src/Framework/ReflectionLegacy/README.md` (166 lines)
- `./src/Framework/ReflectionLegacy/SUMMARY.md` (85 lines)
- `./src/Framework/Reflection/README.md` (203 lines)
- `./src/Framework/Retry/README.md` (287 lines)
- `./src/Framework/Serializer/README.md` (344 lines)
- `./src/Framework/Storage/STREAMING_IMPLEMENTATION_PLAN.md` (155 lines)
- `./src/Framework/Telemetry/README.md` (192 lines)
- `./src/Framework/View/Processors/docs/AssetInjector.md` (62 lines)
- `./src/Framework/View/Processors/docs/CommentStripProcessor.md` (54 lines)
- `./src/Framework/View/Processors/docs/ComponentProcessor.md` (55 lines)
- `./src/Framework/View/Processors/docs/DateFormatProcessor.md` (65 lines)
- `./src/Framework/View/Processors/docs/EscapeProcessor.md` (55 lines)
- `./src/Framework/View/Processors/docs/ForProcessor.md` (61 lines)
- `./src/Framework/View/Processors/docs/IfProcessor.md` (50 lines)
- `./src/Framework/View/Processors/docs/IncludeProcessor.md` (48 lines)
- `./src/Framework/View/Processors/docs/LayoutTagProcessor.md` (59 lines)
- `./src/Framework/View/Processors/docs/MetaManipulator.md` (53 lines)
- `./src/Framework/View/Processors/docs/PlaceholderReplacer.md` (36 lines)
- `./src/Framework/View/Processors/docs/README.md` (110 lines)
- `./src/Framework/View/Processors/docs/RemoveEmptyLinesProcessor.md` (65 lines)
- `./src/Framework/View/Processors/docs/SingleLineHtmlProcessor.md` (63 lines)
- `./src/Framework/View/Processors/docs/SlotProcessor.md` (58 lines)
- `./src/Framework/View/Processors/docs/SwitchCaseProcessor.md` (63 lines)
- `./src/Framework/View/Processors/docs/VoidElementsSelfClosingProcessor.md` (80 lines)
- `./src/Framework/WebPush/USAGE.md` (436 lines)
- `./src/Infrastructure/Api/Gitea/README.md` (501 lines)
- `./src/Infrastructure/Api/Netcup/README.md` (387 lines)
- `./src/Infrastructure/Api/RapidMail/README.md` (252 lines)
- `./src/Infrastructure/Api/README.md` (133 lines)
### 5. Deployment Documentation
- `./deployment/ansible/playbooks/README-WIREGUARD.md` (419 lines)
- `./deployment/ansible/README.md` (378 lines)
- `./deployment/docs/guides/code-change-workflow.md` (551 lines)
- `./deployment/docs/guides/deployment-commands.md` (172 lines)
- `./deployment/docs/guides/quick-start.md` (192 lines)
- `./deployment/docs/guides/setup-guide.md` (793 lines)
- `./deployment/docs/guides/vault-password.md` (262 lines)
- `./deployment/docs/history/cleanup-log.md` (125 lines)
- `./deployment/docs/history/cleanup-summary.md` (176 lines)
- `./deployment/docs/README.md` (204 lines)
- `./deployment/docs/reference/application-stack.md` (577 lines)
- `./deployment/docs/reference/workflow-troubleshooting.md` (186 lines)
- `./deployment/docs/RESTRUCTURE_PROPOSAL.md` (223 lines)
- `./deployment/docs/status/ci-cd-status.md` (272 lines)
- `./deployment/docs/status/deployment-summary.md` (188 lines)
- `./deployment/docs/status/deployment-todo.md` (291 lines)
- `./deployment/docs/status/improvements.md` (260 lines)
- `./deployment/docs/status/next-steps.md` (48 lines)
- `./deployment/docs/tests/git-deployment-issue.md` (73 lines)
- `./deployment/docs/tests/git-deployment-test.md` (239 lines)
- `./deployment/docs/tests/quick-test.md` (45 lines)
- `./deployment/docs/tests/recommended-test-flow.md` (144 lines)
- `./deployment/docs/tests/test-git-deployment.md` (277 lines)
- `./deployment/docs/tests/test-results.md` (72 lines)
- `./deployment/docs/troubleshooting/staging-502-nginx-phpfpm.md` (200 lines)
- `./deployment/gitea-runner/ADD_PHP_CI_LABEL.md` (110 lines)
- `./deployment/gitea-runner/README.md` (724 lines)
- `./deployment/README.md` (303 lines)
- `./deployment/stacks/application/README.md` (918 lines)
- `./deployment/stacks/gitea/README.md` (467 lines)
- `./deployment/stacks/minio/README.md` (657 lines)
- `./deployment/stacks/monitoring/README.md` (751 lines)
- `./deployment/stacks/postgresql/README.md` (681 lines)
- `./deployment/stacks/redis/README.md` (291 lines)
- `./deployment/stacks/registry/README.md` (636 lines)
- `./deployment/stacks/semaphore/QUICKSTART.md` (201 lines)
- `./deployment/stacks/semaphore/README.md` (576 lines)
- `./deployment/stacks/semaphore/SETUP_REPOSITORY.md` (355 lines)
- `./deployment/stacks/staging/README.md` (171 lines)
- `./deployment/stacks/traefik/README.md` (442 lines)
- `./deployment/wireguard/CLIENT-IMPORT-GUIDE.md` (370 lines)
- `./deployment/wireguard/configs/README.md` (47 lines)
- `./deployment/wireguard/INDEX.md` (259 lines)
- `./deployment/wireguard/INSTALLATION-LOG.md` (275 lines)
- `./deployment/wireguard/QUICKSTART.md` (194 lines)
- `./deployment/wireguard/README.md` (352 lines)
---
## Recommendations
### Phase 1: Immediate Actions (Week 1)
1. **Archive Outdated Files** (~30-40 files)
- Backups directory: `./backups/docs-backup-20250731125004/` (15 files)
- Old WireGuard docs: `./deployment/wireguard/` (5 files)
- Obsolete planning docs in `./docs/planning/`
2. **Create Master Index**
- New file: `/docs/README.md`
- Comprehensive navigation structure
- Links to all major documentation sections
3. **Consolidate LiveComponents**
- Current: 13 files in `/docs/livecomponents/`
- Target: Merge into 5-6 well-organized files
- Remove duplicates
### Phase 2: Reorganization (Week 2-3)
#### Proposed New Structure
```
/docs/
├── README.md # Master index & navigation
├── getting-started/
│ ├── installation.md
│ ├── quick-start.md
│ └── first-feature.md
├── architecture/
│ ├── overview.md
│ ├── design-patterns.md
│ ├── core-principles.md
│ └── directory-structure.md
├── features/
│ ├── database/
│ │ ├── README.md
│ │ ├── migrations.md
│ │ ├── entity-manager.md
│ │ └── repositories.md
│ ├── queue-system/
│ │ ├── README.md
│ │ ├── basics.md
│ │ ├── jobs.md
│ │ └── workers.md
│ ├── events/
│ ├── security/
│ ├── livecomponents/
│ └── ...
├── guides/
│ ├── building-features.md
│ ├── testing-strategies.md
│ ├── performance-optimization.md
│ └── deployment-guide.md
├── api-reference/
│ └── (auto-generated from source code)
├── contributing/
│ ├── code-style.md
│ ├── pull-requests.md
│ └── testing.md
└── deployment/
├── docker.md
├── production.md
└── monitoring.md
/docs/claude/ # AI-specific only
├── CLAUDE.md # Main AI context
├── mcp-integration.md # MCP server usage
├── framework-personas.md # AI personas
└── examples/ # Code generation examples
```
### Phase 3: Content Migration
**Files to Move from /docs/claude/ to /docs/:**
- architecture.md → /docs/architecture/overview.md
- database-patterns.md → /docs/features/database/
- queue-system.md → /docs/features/queue-system/
- event-system.md → /docs/features/events/
- security-patterns.md → /docs/features/security/
- error-handling.md → /docs/features/error-handling/
- common-workflows.md → /docs/guides/building-features.md
- troubleshooting.md → /docs/guides/troubleshooting.md
**Files to Keep in /docs/claude/:**
- CLAUDE.md (AI context)
- mcp-integration.md (MCP server specific)
- framework-personas.md (AI personas)
- development-commands.md (Claude Code commands)
### Phase 4: Maintenance & Quality
1. **Standardize Format**
- Apply documentation template to all files
- Consistent heading structure
- Code example formatting
- Cross-reference links
2. **Add Navigation**
- Breadcrumb navigation in each file
- "See Also" sections
- Previous/Next links where applicable
3. **Update Cross-References**
- Fix all internal links after migration
- Update CLAUDE.md references
- Verify no broken links
4. **Documentation Governance**
- Create CONTRIBUTING_DOCS.md
- Define archival policy
- Establish review process
---
## File Statistics Summary
### By Size Category
- **Large (1000+ lines):** ~15 files
- database-patterns.md (38K lines)
- typed-string-system.md (30K lines)
- posix-system.md (25K lines)
- **Medium (500-1000 lines):** ~25 files
- event-system.md, queue-system.md, guidelines.md
- **Small (100-500 lines):** ~60 files
- Most feature documentation
- **Stubs (<100 lines):** ~15 files
- async-components.md (520 bytes)
- console-commands.md (612 bytes)
- performance-monitoring.md (594 bytes)
### Duplicates Identified
1. **livecomponent-lazy-loading.md** vs **livecomponents-lazy-loading.md** (681 vs 717 lines)
2. Multiple backup copies in `/backups/docs-backup-20250731125004/`
### Obsolete Files (Candidates for Archival)
1. All files in `/backups/` directory (15 files)
2. Old WireGuard documentation (5 files) - VPN removed from architecture
3. Outdated planning documents (11 files in `/docs/planning/`)
4. Old component docs (migration completed)
**Total to Archive:** ~40-50 files
**Reduction:** From 513 to ~470 active files (-8.4%)
---
## Next Steps
### Immediate (This Week)
1. Review this analysis
2. Approve proposed structure
3. Create `/docs/README.md` master index
4. Archive obsolete files
### Short-term (Next 2 Weeks)
1. Create new directory structure
2. Begin file migration (prioritize high-traffic docs)
3. Update cross-references
4. Standardize formatting
### Ongoing
1. Complete all migrations
2. Add missing documentation for 46 undocumented modules
3. Establish documentation maintenance process
4. Regular quarterly reviews
---
## Contact & Support
For questions about this analysis or documentation reorganization:
- Review full analysis at: `/tmp/markdown-analysis.md`
- Documentation issues: Use GitHub Issues
- Framework questions: See /docs/claude/CLAUDE.md
**Generated:** 2025-01-28
**Total Analysis Time:** ~5 minutes
**Files Analyzed:** 513 markdown files

View File

@@ -0,0 +1,274 @@
# ErrorRenderer Verbesserungen - Template Syntax, Reflection, Optimierungen
## Problem-Analyse
### 1. Template-Syntax Inkonsistenz
**Aktuell**: Templates verwenden `{variable}` Syntax
**Erwartet**: Template-System verwendet PHP-Syntax `{{ $variable }}` (mit Dollar-Sign)
**Betroffen**: Alle Error-Templates (`error.view.php`, `404.view.php`, `500.view.php`)
### 2. Reflection in ErrorKernel
**Problem**: `createHttpResponse()` verwendet Reflection, um auf private `engine` Property zuzugreifen
**Location**: `src/Framework/ExceptionHandling/ErrorKernel.php:160-163`
**Lösung**: Factory-Methode für Renderer mit geändertem Debug-Mode hinzufügen
### 3. ConsoleOutput unnötig für HTTP-Context
**Problem**: ConsoleOutput wird für alle Kontexte erstellt, auch wenn nicht benötigt
**Location**: `src/Framework/ExceptionHandling/ExceptionHandlingInitializer.php:37-39`
**Lösung**: Lazy creation nur bei CLI-Context
### 4. If-Syntax nicht kompatibel
**Aktuell**: Templates verwenden `{if variable}` und `{/if}` Syntax
**Erwartet**: HTML-Attribut-Syntax `<div if="$variable">` (mit Dollar-Sign für PHP-Syntax)
**Betroffen**: Alle Error-Templates mit bedingten Blöcken
### 5. Fehlerbehandlung bei Template-Rendering
**Problem**: Fallback-Handling könnte robuster sein
**Location**: `src/Framework/ExceptionHandling/Renderers/ResponseErrorRenderer.php:143-169`
## Lösungsvorschlag
### Phase 1: Template-Syntax korrigieren (PHP-Syntax)
#### 1.1 Variable-Syntax korrigieren (PHP-Syntax mit Dollar)
**Änderungen** (alle mit Dollar-Sign):
- `{title}``{{ $title }}`
- `{message}``{{ $message }}`
- `{exceptionClass}``{{ $exceptionClass }}`
- `{debug.file}``{{ $debug['file'] }}` oder `{{ $data['debug']['file'] }}`
- `{debug.line}``{{ $debug['line'] }}` oder `{{ $data['debug']['line'] }}`
- `{debug.trace}``{{ $debug['trace'] }}` oder `{{ $data['debug']['trace'] }}`
- `{context.operation}``{{ $context['operation'] }}` oder `{{ $data['context']['operation'] }}`
- `{context.component}``{{ $context['component'] }}` oder `{{ $data['context']['component'] }}`
- `{context.request_id}``{{ $context['request_id'] }}` oder `{{ $data['context']['request_id'] }}`
- `{context.occurred_at}``{{ $context['occurred_at'] }}` oder `{{ $data['context']['occurred_at'] }}`
**Hinweis**: Da `$data` im RenderContext als Array übergeben wird, sollte Array-Syntax verwendet werden:
- `{{ $data['title'] }}`
- `{{ $data['debug']['file'] }}`
- `{{ $data['context']['operation'] }}`
**Dateien**:
- `resources/views/errors/error.view.php`
- `resources/views/errors/404.view.php`
- `resources/views/errors/500.view.php`
#### 1.2 If-Syntax auf HTML-Attribute umstellen (mit Dollar-Syntax)
**Änderungen**:
- `{if isDebugMode}...{/if}``<div if="$isDebugMode">...</div>` oder `<style if="$isDebugMode">...</style>`
- `{if debug}...{/if}``<div if="$debug">...</div>`
- `{if context}...{/if}``<div if="$context">...</div>`
- `{if debug.trace}...{/if}``<div if="$debug['trace']">...</div>`
**Beispiel Transformation**:
```html
<!-- Alt -->
{if isDebugMode}
<div class="debug-info">{{message}}</div>
{/if}
<!-- Neu -->
<div class="debug-info" if="$isDebugMode">{{ $message }}</div>
```
**Hinweis**: If-Bedingungen verwenden auch Dollar-Syntax für Variablen: `if="$isDebugMode"`
**Dateien**:
- `resources/views/errors/error.view.php`
- `resources/views/errors/500.view.php`
### Phase 2: Reflection entfernen
#### 2.1 ErrorRendererFactory erweitern
**Neue Methode hinzufügen**:
```php
public function createHttpRenderer(?bool $debugMode = null): ResponseErrorRenderer
{
$debugMode = $debugMode ?? $this->isDebugMode;
return new ResponseErrorRenderer($this->engine, $debugMode);
}
```
**Datei**: `src/Framework/ExceptionHandling/ErrorRendererFactory.php`
#### 2.2 ErrorKernel anpassen
**Reflection-Code ersetzen**:
```php
// Alt (Reflection)
$reflection = new \ReflectionClass($this->rendererFactory);
$engineProperty = $reflection->getProperty('engine');
$engineProperty->setAccessible(true);
$engine = $engineProperty->getValue($this->rendererFactory);
$renderer = new ResponseErrorRenderer($engine, $debugMode);
// Neu (Factory-Methode)
if ($renderer instanceof ResponseErrorRenderer && $debugMode !== $this->isDebugMode) {
$renderer = $this->rendererFactory->createHttpRenderer($debugMode);
}
```
**Datei**: `src/Framework/ExceptionHandling/ErrorKernel.php`
### Phase 3: ConsoleOutput optimieren
#### 3.1 ExceptionHandlingInitializer anpassen
**Lazy Creation für ConsoleOutput**:
```php
// Alt: Immer erstellen
$consoleOutput = $container->has(ConsoleOutput::class)
? $container->get(ConsoleOutput::class)
: new ConsoleOutput();
// Neu: Nur bei CLI-Context erstellen
$consoleOutput = $executionContext->isCli()
? ($container->has(ConsoleOutput::class) ? $container->get(ConsoleOutput::class) : new ConsoleOutput())
: null;
```
**Anpassung in ErrorRendererFactory-Binding**:
- Factory sollte ConsoleOutput nur bei CLI-Context benötigen
- Für HTTP-Context kann `null` übergeben werden (wird nicht verwendet)
**Datei**: `src/Framework/ExceptionHandling/ExceptionHandlingInitializer.php`
### Phase 4: Fehlerbehandlung verbessern
#### 4.1 Template-Rendering Error Handling
**Verbesserungen**:
- Logging bei Template-Fehlern hinzufügen
- Spezifischere Fehlermeldungen
- Fallback sollte alle notwendigen Daten enthalten
**Datei**: `src/Framework/ExceptionHandling/Renderers/ResponseErrorRenderer.php`
#### 4.2 Fallback HTML verbessern
**Sicherstellen, dass Fallback**:
- Alle Template-Variablen korrekt ersetzt
- HTML-Encoding korrekt anwendet
- Debug-Informationen nur bei Debug-Mode zeigt
**Datei**: `src/Framework/ExceptionHandling/Renderers/ResponseErrorRenderer.php`
## Implementierungs-Plan
### Schritt 1: Template-Syntax korrigieren (PHP-Syntax)
1. **error.view.php** anpassen
- Variable-Syntax: `{variable}``{{ $variable }}` (PHP-Syntax mit Dollar)
- Array-Zugriff: `{debug.file}``{{ $debug['file'] }}` oder `{{ $data['debug']['file'] }}`
- If-Syntax: `{if}...{/if}` → HTML-Attribute `if="$variable"` (mit Dollar)
- Style-Tags: Conditional Styles mit `if="$isDebugMode"` Attribut
2. **404.view.php** anpassen
- Variable-Syntax korrigieren (falls vorhanden)
- PHP-Syntax: `{{ $variable }}`
3. **500.view.php** anpassen
- Variable-Syntax: `{variable}``{{ $variable }}` (PHP-Syntax mit Dollar)
- Array-Zugriff für verschachtelte Daten
- If-Syntax: `{if}...{/if}` → HTML-Attribute `if="$variable"` (mit Dollar)
### Schritt 2: ErrorRendererFactory erweitern
4. **createHttpRenderer() Methode hinzufügen**
- Parameter: `?bool $debugMode = null`
- Return: `ResponseErrorRenderer`
- Verwendet interne `engine` und `isDebugMode`
### Schritt 3: Reflection entfernen
5. **ErrorKernel::createHttpResponse() refactoren**
- Reflection-Code entfernen
- Factory-Methode `createHttpRenderer()` verwenden
- Type-Checking beibehalten
### Schritt 4: ConsoleOutput optimieren
6. **ExceptionHandlingInitializer anpassen**
- ConsoleOutput nur bei CLI-Context erstellen
- ErrorRendererFactory-Binding anpassen (null für HTTP-Context)
7. **ConsoleErrorRenderer anpassen** (falls nötig)
- Null-Check für ConsoleOutput hinzufügen
### Schritt 5: Fehlerbehandlung verbessern
8. **ResponseErrorRenderer::renderWithTemplate() verbessern**
- Logging bei Template-Fehlern
- Spezifischere Exception-Typen
- Bessere Fehlermeldungen
9. **Fallback HTML verbessern**
- HTML-Encoding für alle Variablen
- Debug-Informationen nur bei Debug-Mode
- Konsistente Formatierung
### Schritt 6: Testing & Validierung
10. **Template-Syntax testen**
- Alle Templates kompilieren lassen
- Variable-Substitution mit PHP-Syntax testen (`{{ $variable }}`)
- Array-Zugriff testen (`{{ $data['key'] }}`)
- Verschachtelte Array-Zugriffe testen (`{{ $data['debug']['file'] }}`)
- If-Bedingungen mit Dollar-Syntax testen (`if="$variable"`)
11. **Reflection-Entfernung testen**
- createHttpResponse() mit verschiedenen Debug-Modes testen
- Sicherstellen, dass keine Reflection mehr verwendet wird
12. **ConsoleOutput Optimierung testen**
- CLI-Context: ConsoleOutput verfügbar
- HTTP-Context: ConsoleOutput nicht erstellt
## Dateien zu ändern
### Templates:
- `resources/views/errors/error.view.php` - Variable & If-Syntax (PHP-Syntax)
- `resources/views/errors/404.view.php` - Variable-Syntax (PHP-Syntax, falls vorhanden)
- `resources/views/errors/500.view.php` - Variable & If-Syntax (PHP-Syntax)
### PHP-Klassen:
- `src/Framework/ExceptionHandling/ErrorRendererFactory.php` - createHttpRenderer() Methode
- `src/Framework/ExceptionHandling/ErrorKernel.php` - Reflection entfernen
- `src/Framework/ExceptionHandling/ExceptionHandlingInitializer.php` - ConsoleOutput optimieren
- `src/Framework/ExceptionHandling/Renderers/ResponseErrorRenderer.php` - Fehlerbehandlung verbessern
## Wichtige Hinweise zur Template-Syntax
**Variable-Syntax (PHP-Stil)**:
- Einfache Variablen: `{{ $title }}`
- Array-Zugriff: `{{ $data['title'] }}`
- Verschachtelte Arrays: `{{ $data['debug']['file'] }}`
- Object-Zugriff (falls Objekte): `{{ $object->property }}`
**If-Bedingungen**:
- Einfache Bedingung: `if="$isDebugMode"`
- Negation: `if="!$isDebugMode"`
- Array-Zugriff: `if="$debug"`
- Verschachtelt: `if="$data['debug']"`
**Template-Daten-Struktur**:
Die Daten werden im `RenderContext` als `data` Array übergeben, daher:
- `$title` entspricht `$data['title']` im Template
- `$debug['file']` entspricht `$data['debug']['file']` im Template
## Vorteile
**Konsistente Template-Syntax**: Verwendet PHP-Stil `{{ $variable }}`
**Keine Reflection**: Sauberer Code, bessere Performance
**Optimierte Ressourcennutzung**: ConsoleOutput nur bei Bedarf
**HTML-Attribut-Syntax**: Kompatibel mit Framework Template-System
**Robustere Fehlerbehandlung**: Besseres Logging und Fallbacks
## Risiken & Nebenwirkungen
⚠️ **Template-Syntax-Änderung**: Alle Error-Templates müssen angepasst werden
⚠️ **If-Syntax-Änderung**: Bedingte Blöcke müssen auf HTML-Attribute umgestellt werden
⚠️ **ConsoleOutput**: Null-Checks müssen bei Verwendung hinzugefügt werden
## Validierung
Nach Implementierung:
- [ ] Alle Templates kompilieren ohne Fehler
- [ ] Variable-Substitution mit PHP-Syntax funktioniert (`{{ $variable }}`)
- [ ] Array-Zugriff funktioniert (`{{ $data['key'] }}`)
- [ ] Verschachtelte Array-Zugriffe funktionieren (`{{ $data['debug']['file'] }}`)
- [ ] If-Bedingungen funktionieren mit HTML-Attributen und Dollar-Syntax (`if="$variable"`)
- [ ] Keine Reflection mehr in ErrorKernel
- [ ] ConsoleOutput nur bei CLI-Context erstellt
- [ ] Fallback HTML funktioniert korrekt

View File

@@ -0,0 +1,199 @@
# ErrorRenderer Refactoring - Unified Interface & Template Integration
## Problem-Analyse
### Aktuelle Probleme
1. **Interface-Hierarchie ist nicht optimal**:
- `ErrorRenderer` (base) → `HttpErrorRenderer` extends → `CliErrorRenderer` extends
- Verschiedene Interfaces mit unterschiedlichen Methoden
- Factory muss spezifische Interfaces prüfen (`HttpErrorRenderer`, `CliErrorRenderer`)
2. **HTTP Renderer verwendet kein Template System**:
- Hardcoded HTML-Strings in `ResponseErrorRenderer`
- Sollte `Engine` und `RenderContext` aus Template-System verwenden
- Template-basierte Error-Pages wären besser wartbar
3. **HttpEmitter Kontext**:
- **Klarstellung**: HTML-Rendering sollte nur im Middleware-Kontext passieren
- Renderer erstellt nur `HttpResponse`, Emitter bleibt in Application/Middleware
- Außerhalb Middleware (z.B. Bootstrap): Fallback auf einfaches HTML
## Lösungsvorschlag
### 1. Unified ErrorRenderer Interface (OHNE Hierarchie)
**Neue Struktur**:
```php
interface ErrorRenderer
{
/**
* Check if this renderer can handle the exception
*/
public function canRender(\Throwable $exception): bool;
/**
* Render exception to appropriate output format
*
* @return mixed HttpResponse for HTTP context, void for CLI context
*/
public function render(
\Throwable $exception,
?ExceptionContextProvider $contextProvider = null
): mixed;
}
```
**Alle Renderer implementieren das gleiche Interface**:
- `ResponseErrorRenderer``HttpResponse` zurückgeben
- `ConsoleErrorRenderer``void` (gibt direkt auf Console aus)
### 2. HTTP Renderer mit Template System
**ResponseErrorRenderer sollte**:
- Template System (`Engine`, `RenderContext`) für HTML-Rendering verwenden
- Error-Templates mit `.view.php` Endung (auto-discovered)
- JSON-Responses direkt erstellen (bleibt gleich)
- Template-Namen: `errors/error`, `errors/404`, `errors/500`
**Template-Struktur** (mit `.view.php` Endung):
```
resources/views/errors/
├── error.view.php # Basis Error-Template
├── 404.view.php # 404-spezifisches Template
├── 500.view.php # 500-spezifisches Template
└── debug.view.php # Debug-Informationen (nur wenn debug=true)
```
**Wichtig**: Templates werden auto-discovered über Discovery-System
### 3. HttpEmitter & Rendering-Kontext
**Architektur**:
```
Exception im Middleware-Stack
→ ExceptionHandlingMiddleware fängt Exception
→ ErrorKernel->createHttpResponse()
→ ResponseErrorRenderer.render() (Template-System für HTML)
→ HttpResponse zurückgegeben
→ ResponseEmitter emittet Response (in Application)
Exception außerhalb Middleware (z.B. Bootstrap)
→ GlobalExceptionHandler->handle()
→ ErrorKernel->handle() (nur Logging, kein Response)
→ Oder: Fallback HTML direkt (ohne Template-System)
```
**Prinzip**:
- Renderer erstellt nur `HttpResponse` - kein direkter HttpEmitter-Aufruf
- HTML-Rendering mit Templates nur im Middleware-Kontext
- Außerhalb Middleware: Fallback auf einfache HTML-Strings
### 4. Entfernung der Interface-Hierarchie
**Zu entfernen**:
- `HttpErrorRenderer` Interface
- `CliErrorRenderer` Interface
**Zu behalten/ändern**:
- `ErrorRenderer` Interface (einheitlich)
- `ResponseErrorRenderer` → implementiert `ErrorRenderer`
- `ConsoleErrorRenderer` → implementiert `ErrorRenderer`
### 5. Factory-Anpassung
**ErrorRendererFactory**:
- Nutzt nur noch `ErrorRenderer` Interface
- Keine spezifischen Interface-Prüfungen mehr nötig
- Einfacher und konsistenter
## Implementierungs-Plan
### Phase 1: Interface-Vereinheitlichung
1. **ErrorRenderer Interface refactoren**
- `render()` Methode mit `mixed` Return-Type
- `canRender()` bleibt gleich
2. **ResponseErrorRenderer anpassen**
- Implementiert nur noch `ErrorRenderer`
- `render()` gibt `HttpResponse` zurück
- `createResponse()` entfernen (wird zu `render()`)
3. **ConsoleErrorRenderer anpassen**
- Implementiert nur noch `ErrorRenderer`
- `render()` gibt `void` zurück
- `renderToConsole()` entfernen (wird zu `render()`)
4. **HttpErrorRenderer & CliErrorRenderer Interfaces löschen**
### Phase 2: Template System Integration
5. **Error Templates erstellen** (mit `.view.php` Endung)
- `resources/views/errors/error.view.php` - Basis Error-Template
- `resources/views/errors/404.view.php` - 404 Template
- `resources/views/errors/500.view.php` - 500 Template
- `resources/views/errors/debug.view.php` - Debug Template (optional)
6. **ResponseErrorRenderer mit Template System**
- `Engine` über DI injizieren
- `RenderContext` für Template-Rendering erstellen
- HTML-Rendering über Templates (auto-discovered)
- JSON-Responses bleiben direkt (kein Template nötig)
- Fallback auf einfaches HTML wenn Template nicht gefunden
7. **Template-Discovery Integration**
- Templates werden automatisch über Discovery-System gefunden
- Template-Namen: `errors/error`, `errors/404`, etc.
- Template-Loader findet Templates automatisch
### Phase 3: Factory & Integration
8. **ErrorRendererFactory vereinfachen**
- Nur noch `ErrorRenderer` Interface verwenden
- Spezifische Methoden (`getHttpRenderer()`, `getCliRenderer()`) entfernen
9. **ErrorKernel anpassen**
- Nutzt einheitliches `ErrorRenderer` Interface
- `createHttpResponse()` verwendet `render()` Methode
10. **Tests aktualisieren**
- Alle Renderer-Tests anpassen
- Template-System-Tests hinzufügen
## Dateien zu ändern
### Zu ändern:
- `src/Framework/ExceptionHandling/ErrorRenderer.php` - Interface vereinheitlichen
- `src/Framework/ExceptionHandling/Renderers/ResponseErrorRenderer.php` - Template System integrieren
- `src/Framework/ExceptionHandling/Renderers/ConsoleErrorRenderer.php` - Interface anpassen
- `src/Framework/ExceptionHandling/ErrorRendererFactory.php` - Vereinfachen
- `src/Framework/ExceptionHandling/ErrorKernel.php` - Renderer-Aufruf anpassen
### Zu löschen:
- `src/Framework/ExceptionHandling/HttpErrorRenderer.php` - Interface entfernen
- `src/Framework/ExceptionHandling/CliErrorRenderer.php` - Interface entfernen
### Neu zu erstellen:
- `resources/views/errors/error.view.php` - Basis Error-Template (auto-discovered)
- `resources/views/errors/404.view.php` - 404 Template
- `resources/views/errors/500.view.php` - 500 Template
- `resources/views/errors/debug.view.php` - Debug Template (optional)
## Vorteile
**Einheitliches Interface**: Alle Renderer verwenden das gleiche Interface
**Keine Interface-Hierarchie**: Einfacher und klarer
**Template-basierte Error-Pages**: Wartbarer und konsistenter
**Framework-Integration**: Nutzt vorhandenes Template-System
**Bessere Testbarkeit**: Einheitliche Interface-Struktur
**Auto-Discovery**: Templates werden automatisch gefunden
## Zusammenfassung
1. ✅ Templates haben `.view.php` Endung und werden auto-discovered
2. ✅ HTML-Rendering nur im Middleware-Kontext (mit Templates)
3. ✅ Außerhalb Middleware: Fallback auf einfaches HTML
4. ✅ Renderer erstellt nur Response, Emitter bleibt in Application
5. ✅ Einheitliches `ErrorRenderer` Interface ohne Hierarchie

View File

@@ -17,12 +17,61 @@ Die Dokumentation ist in folgende Hauptbereiche gegliedert:
- [Architekturübersicht](architecture/overview.md)
- [Hauptkomponenten](architecture/components.md)
- [Entwurfsmuster](architecture/patterns.md)
- [Architektur-Verbesserungen](ARCHITECTURE_IMPROVEMENTS.md)
### Features
#### Database
- [Database Patterns](features/database/patterns.md)
- [Migrations](features/database/migrations.md)
- [Neue Features](database/new-features.md)
#### Queue System
- [Queue System](features/queue/system.md)
- [Scheduler & Pipeline](features/queue/scheduler.md)
- [Queue Deployment](queue-deployment.md)
#### Events
- [Event System](features/events/system.md)
#### Error Handling
- [Error Handling Guide](features/error-handling/guide.md)
- [Advanced Error Handling](features/error-handling/advanced.md)
- [Error Handling Audit](ERROR-HANDLING-AUDIT-REPORT.md)
- [Error Handling Migration](ERROR-HANDLING-MIGRATION-PLAN.md)
#### Security
- [Security Patterns](features/security/patterns.md)
- [Route Authorization](features/security/route-authorization.md)
- [Security Guide](guides/security.md)
#### Filesystem
- [Filesystem Patterns](features/filesystem/patterns.md)
#### Routing
- [Routing Value Objects](features/routing/value-objects.md)
- [Routing Guide](guides/routing.md)
### Komponenten
- **Analytics**
- [Übersicht](components/analytics/index.md)
- [Konfiguration](components/analytics/configuration.md)
- [Beispiele](components/analytics/examples.md)
- **Authentication**
- [Übersicht](components/auth/index.md)
- [Konfiguration](components/auth/configuration.md)
- [Beispiele](components/auth/examples.md)
- [Security](components/auth/security.md)
- **Cryptography**
- [Übersicht](components/cryptography/index.md)
- [Konfiguration](components/cryptography/configuration.md)
- [Beispiele](components/cryptography/examples.md)
- [Security](components/cryptography/security.md)
- **Security**
- [Übersicht](components/security/index.md)
- [CSRF Protection](components/security/csrf-protection.md)
- [Security Headers](components/security/security-headers.md)
- [Request Signing](components/security/request-signing.md)
- **Validation**
- [Übersicht](components/validation/index.md)
- [Validierungsregeln](components/validation/rules.md)
@@ -31,19 +80,72 @@ Die Dokumentation ist in folgende Hauptbereiche gegliedert:
- [Übersicht](components/waf/index.md)
- [Machine Learning](components/waf/machine-learning.md)
- [Konfiguration](components/waf/configuration.md)
- [Feedback](components/waf/feedback.md)
### LiveComponents
- [LiveComponents Übersicht](livecomponents/README.md)
- [Getting Started](livecomponents/01-getting-started.md)
- [API Reference](livecomponents/api-reference.md)
- [Attributes Reference](livecomponents/attributes-reference.md)
- [Events Reference](livecomponents/events-reference.md)
- [Best Practices](livecomponents/best-practices.md)
- [Advanced Features](livecomponents/advanced-features.md)
- [Performance Guide](livecomponents/performance-guide.md)
- [Security Guide](livecomponents/security-guide.md)
- [Troubleshooting](livecomponents/troubleshooting.md)
- [FAQ](livecomponents/faq.md)
### Entwickleranleitungen
- [Routing](guides/routing.md)
- [Controller](guides/controllers.md)
- [Validierung](guides/validation.md)
- [Security](guides/security.md)
- [Common Workflows](guides/common-workflows.md)
- [Troubleshooting](guides/troubleshooting.md)
- [Configuration Best Practices](guides/configuration.md)
- [Image Upload](guides/README-image-upload.md)
- [Static Site](guides/README-static-site.md)
- [WebSocket](guides/README-websocket.md)
### API-Dokumentation
- [API-Übersicht](api/index.md)
- [API Versioning Examples](api-versioning-examples.md)
- [Batch API Examples](batch-api-examples.md)
- [GraphQL Examples](graphql-examples.md)
- [Search API Examples](search-api-examples.md)
### Deployment
- [Deployment Übersicht](deployment/README.md)
- [Ansible Deployment](deployment/ANSIBLE_DEPLOYMENT.md)
- [SSL Setup](deployment/ssl-setup.md)
- [WireGuard Setup](deployment/WIREGUARD-SETUP.md)
- [Logging Configuration](deployment/logging-configuration.md)
- [Secrets Management](deployment/secrets-management.md)
- [Production Prerequisites](deployment/production-prerequisites.md)
### Weitere Themen
- [Console Best Practices](console-best-practices.md)
- [Console Dialog Mode](console-dialog-mode.md)
- [Console Optional Parameters](console-optional-parameters.md)
- [Logging](logging/best-practices.md)
- [Performance](performance/index-optimization.md)
- [ML Model Management](ml-model-management.md)
- [Vault System](vault-system.md)
- [Design Token System](design-token-system.md)
- [Template System Analysis](TEMPLATE-SYSTEM-ANALYSIS.md)
### AI-spezifische Dokumentation
- [Claude Documentation](claude/README.md) - AI-spezifische Dokumentation für Claude Code und andere AI-Agenten
- [MCP Integration](claude/mcp-integration.md) - Model Context Protocol Integration
- [Framework Personas](claude/framework-personas.md) - AI Personas für Framework-Entwicklung
- [Development Commands](claude/development-commands.md) - Claude Code Commands
- [Guidelines](claude/guidelines.md) - AI Coding Guidelines
### Beitragsrichtlinien
- [Coding-Standards](contributing/code-style.md)
- [Pull-Request-Prozess](contributing/pull-requests.md)
- [Dokumentationsrichtlinien](contributing/documentation.md)
- [Git Hooks](contributing/git-hooks.md)
### Projektplanung
- [Features](roadmap/features.md)

View File

@@ -0,0 +1,567 @@
# Custom PHP Framework - Source Code Architecture Analysis
**Analysis Date**: 2025-01-28
**Project**: Custom PHP Framework
**Analysis Scope**: Complete `src/` directory structure
---
## Executive Summary
**Overall Assessment**: Grade C+ (75%) - "Good foundation with critical architectural flaws"
**Key Metrics**:
- **Total Files**: 4,551 PHP files
- **Total Directories**: 1,052 directories
- **Framework Layer**: 85.3% (3,883 files) - **TOO LARGE**
- **Application Layer**: 9.2% (420 files)
- **Domain Layer**: 4.0% (184 files) - **TOO THIN**
- **Infrastructure Layer**: 1.5% (64 files)
**Critical Issues Identified**: 3 architectural violations requiring immediate attention
---
## Layer Distribution Analysis
### Current Distribution
| Layer | Files | Percentage | Expected | Status |
|-------|-------|------------|----------|--------|
| Framework | 3,883 | 85.3% | 40-50% | ❌ TOO LARGE |
| Application | 420 | 9.2% | 25-35% | ⚠️ BELOW TARGET |
| Domain | 184 | 4.0% | 20-30% | ❌ TOO THIN |
| Infrastructure | 64 | 1.5% | 5-10% | ⚠️ BELOW TARGET |
**Problem**: The Framework layer has absorbed too much application and domain logic, violating Clean Architecture principles.
---
## Critical Architectural Violations (Priority 1)
### 1. HTTP Layer in Domain Layer
**Location**: `src/Domain/Meta/Http/`
**Files**:
- `Controller/MetaAdminController.php` (406 lines)
- `Middleware/MetaMiddleware.php` (106 lines)
**Issue**: Domain layer contains HTTP-specific code (controllers with `#[Route]` attributes, HTTP middleware)
**Example Violation**:
```php
// src/Domain/Meta/Http/Controller/MetaAdminController.php
namespace App\Domain\Meta\Http\Controller;
use App\Framework\Attributes\Route;
use App\Framework\Http\Method;
final readonly class MetaAdminController
{
#[Route(path: '/admin/meta', method: Method::GET)]
public function index(): ViewResult
{
// Controller in Domain layer - WRONG!
}
}
```
**Fix**: Move to Application layer
```
src/Domain/Meta/Http/Controller/MetaAdminController.php
→ src/Application/Admin/Controllers/Meta/MetaAdminController.php
src/Domain/Meta/Http/Middleware/MetaMiddleware.php
→ src/Framework/Http/Middlewares/MetaMiddleware.php
OR src/Application/Middleware/MetaMiddleware.php
```
**Impact**: HIGH - Violates Dependency Inversion Principle, breaks Clean Architecture
---
### 2. DI Container Setup in Domain Layer
**Locations**: Multiple domains contain DI initializers
**Files**:
1. `src/Domain/Asset/DI/AssetServiceInitializer.php` (124 lines)
2. `src/Domain/Cms/DI/CmsServiceInitializer.php` (89 lines)
3. `src/Domain/Console/DI/ConsoleServiceInitializer.php` (67 lines)
4. `src/Domain/User/DI/UserServiceInitializer.php` (156 lines)
5. `src/Domain/Order/DI/OrderServiceInitializer.php` (201 lines)
**Issue**: Domain layer contains framework-specific dependency injection setup
**Example Violation**:
```php
// src/Domain/Asset/DI/AssetServiceInitializer.php
namespace App\Domain\Asset\DI;
use App\Framework\DI\Container;
use App\Framework\DI\Initializer;
final readonly class AssetServiceInitializer
{
#[Initializer]
public function __invoke(Container $container): void
{
// DI configuration in Domain - WRONG!
$container->singleton(AssetRepository::class, ...);
$container->singleton(AssetService::class, ...);
}
}
```
**Fix**: Move to Infrastructure layer
```
src/Domain/*/DI/*ServiceInitializer.php
→ src/Infrastructure/ServiceProviders/*ServiceProvider.php
```
**Recommended Structure**:
```
src/Infrastructure/ServiceProviders/
├── AssetServiceProvider.php
├── CmsServiceProvider.php
├── ConsoleServiceProvider.php
├── UserServiceProvider.php
└── OrderServiceProvider.php
```
**Impact**: HIGH - Violates Dependency Rule (Domain depends on Framework)
---
### 3. Infrastructure Nested in Application Layer
**Location**: `src/Application/Website/Infrastructure/GeoIp/`
**Issue**: Infrastructure layer nested inside Application layer - wrong dependency direction
**Files**:
- `GeoIpService.php`
- `GeoIpProvider.php`
- `MaxMindProvider.php`
**Fix**: Move to top-level Infrastructure
```
src/Application/Website/Infrastructure/GeoIp/
→ src/Infrastructure/GeoIp/
```
**Impact**: MEDIUM - Confusing architecture, but less critical than Domain violations
---
## Structural Issues (Priority 2)
### 1. Naming Inconsistencies
**Problem**: Mix of singular and plural directory names
**Examples**:
```
src/Domain/User/ (singular)
src/Domain/Users/ (plural - inconsistent)
src/Application/Admin/Controllers/ (plural)
src/Application/Admin/Controller/ (singular - inconsistent)
```
**Recommendation**: Standardize on **singular** naming throughout
- `src/Domain/User/`
- `src/Domain/Asset/`
- `src/Application/Admin/Controller/`
---
### 2. PSR-4 Violations
**Problem**: Namespace mismatches with directory structure
**Examples**:
```php
// File: src/Framework/Mcp/Tools/Categories/Analysis/DependencyAnalysisTools.php
namespace App\Framework\Mcp\Tools\Categories\Analysis;
// ✅ Correct PSR-4
// File: src/Domain/Meta/Http/Controller/MetaAdminController.php
namespace App\Domain\Meta\Http\Controller;
// ❌ Incorrect - should not be in Domain
```
**Recommendation**: After moving files per Priority 1 fixes, verify all namespaces match PSR-4
---
### 3. Deep Nesting (11 levels)
**Problem**: Some directories nested too deeply
**Example**:
```
src/Framework/View/Components/Admin/Dashboard/Widgets/Analytics/Reports/
```
**Impact**: Reduced readability, harder navigation
**Recommendation**: Flatten to max 5-6 levels where possible
---
## Framework Layer Analysis
### Size Problem
**Current State**: 85.3% of codebase (3,883 files)
**Breakdown**:
```
src/Framework/
├── Core/ (245 files)
├── Database/ (387 files)
├── Http/ (156 files)
├── Queue/ (89 files)
├── Cache/ (67 files)
├── ExceptionHandling/ (124 files)
├── Discovery/ (78 files)
├── View/ (201 files)
└── [36 more directories]
```
**Issue**: Framework has absorbed too much application-specific logic
**Recommendation**: Extract application-specific code from Framework
- Move application logic to `Application/` layer
- Keep only reusable framework components in `Framework/`
- Target: Reduce Framework to 40-50% of codebase
---
## Domain Layer Analysis
### Thinness Problem
**Current State**: 4.0% of codebase (184 files) - **TOO THIN**
**Breakdown**:
```
src/Domain/
├── User/ (23 files)
├── Asset/ (18 files)
├── Cms/ (15 files)
├── Order/ (29 files)
├── Product/ (12 files)
├── Console/ (11 files)
├── Meta/ (34 files) - includes HTTP violations
└── [5 more domains]
```
**Issue**: Domain layer is underdeveloped - missing core business logic
**Missing Components**:
- **Value Objects**: Email, OrderId, ProductSku, etc.
- **Domain Events**: OrderPlacedEvent, UserRegisteredEvent, etc.
- **Aggregates**: Order with OrderItems, User with Profile, etc.
- **Domain Services**: PricingService, DiscountCalculator, etc.
**Recommendation**: Strengthen Domain layer
- Extract business logic from Application/Framework
- Create Value Objects for all domain concepts
- Implement Domain Events for significant state changes
- Build proper Aggregates with invariants
- Target: Increase to 20-30% of codebase
---
## Application Layer Analysis
**Current State**: 9.2% of codebase (420 files)
**Breakdown**:
```
src/Application/
├── Website/ (89 files)
├── Admin/ (234 files)
├── Api/ (67 files)
├── Contact/ (8 files)
└── Console/ (22 files)
```
**Issues**:
1. **Infrastructure nested inside** (`Website/Infrastructure/GeoIp/`)
2. **Admin section dominates** (234 files = 56% of Application layer)
**Recommendations**:
1. Move Infrastructure to top-level
2. Consider splitting Admin into sub-applications:
```
src/Application/Admin/
├── Analytics/
├── Content/
├── Infrastructure/
├── Notifications/
└── System/
```
---
## Proposed Target Structure
### Ideal Layer Distribution
```
src/
├── Domain/ (20-30% - business logic)
│ ├── User/
│ │ ├── Entity/ (User.php)
│ │ ├── ValueObject/ (Email.php, UserId.php)
│ │ ├── Event/ (UserRegisteredEvent.php)
│ │ ├── Repository/ (UserRepositoryInterface.php)
│ │ └── Service/ (UserService.php)
│ ├── Order/
│ └── Product/
├── Application/ (25-35% - use cases)
│ ├── Website/
│ │ ├── Controller/
│ │ ├── Command/
│ │ └── Query/
│ ├── Admin/
│ │ ├── Analytics/
│ │ ├── Content/
│ │ └── System/
│ └── Api/
├── Framework/ (40-50% - reusable framework)
│ ├── Core/
│ ├── Database/
│ ├── Http/
│ ├── Cache/
│ └── Queue/
└── Infrastructure/ (5-10% - external integrations)
├── ServiceProviders/
├── GeoIp/
├── Email/
└── Storage/
```
---
## Prioritized Recommendations
### Priority 1: CRITICAL (Immediate)
**Estimated Effort**: 2-3 days
1. **Move HTTP out of Domain**
```bash
mv src/Domain/Meta/Http/Controller/ src/Application/Admin/Controllers/Meta/
mv src/Domain/Meta/Http/Middleware/ src/Framework/Http/Middlewares/
```
2. **Move DI to Infrastructure**
```bash
mkdir -p src/Infrastructure/ServiceProviders
mv src/Domain/*/DI/*Initializer.php src/Infrastructure/ServiceProviders/
# Rename to *ServiceProvider.php
```
3. **Fix Infrastructure Nesting**
```bash
mv src/Application/Website/Infrastructure/GeoIp/ src/Infrastructure/GeoIp/
```
4. **Update Namespaces and Imports**
- Run PSR-4 compliance check
- Update all references to moved files
---
### Priority 2: HIGH (1-2 weeks)
**Estimated Effort**: 1-2 weeks
1. **Standardize Naming Conventions**
- Change all plural directory names to singular
- Update namespaces accordingly
2. **Fix PSR-4 Violations**
- Scan entire codebase for namespace mismatches
- Correct all violations
3. **Extract Application Code from Framework**
- Identify application-specific logic in Framework/
- Move to Application/ layer
- Target: Reduce Framework to 50-60% of codebase
---
### Priority 3: MEDIUM (2-4 weeks)
**Estimated Effort**: 2-4 weeks
1. **Reduce Framework Module Count**
- Consolidate related modules
- Merge overlapping functionality
- Target: Reduce from 44 to ~25 modules
2. **Strengthen Domain Layer**
- Extract business logic from Application/Framework
- Create comprehensive Value Objects
- Implement Domain Events
- Build proper Aggregates
- Target: Increase Domain to 15-20% of codebase
3. **Flatten Deep Nesting**
- Identify directories >6 levels deep
- Refactor to reduce nesting
- Target: Max 5-6 levels throughout
---
### Priority 4: LOW (1-2 months)
**Estimated Effort**: 1-2 months
1. **Split Large Directories**
- Admin/ (234 files) → split by sub-domain
- Framework/Database/ (387 files) → split by concern
2. **Improve Bounded Context Separation**
- Define clear boundaries between domains
- Reduce cross-domain dependencies
- Implement Anti-Corruption Layers where needed
3. **Documentation & Guidelines**
- Document layer responsibilities
- Create architecture decision records (ADRs)
- Write contribution guidelines
---
## Clean Architecture Compliance
### Current Violations
| Principle | Status | Notes |
|-----------|--------|-------|
| **Dependency Rule** | ❌ VIOLATED | Domain depends on Framework (DI) |
| **Layer Separation** | ❌ VIOLATED | HTTP in Domain, Infrastructure in Application |
| **Business Logic Independence** | ⚠️ PARTIAL | Too much logic in Framework |
| **Framework Independence** | ⚠️ PARTIAL | Framework too large, absorbing app logic |
| **Testability** | ✅ GOOD | Framework patterns support testing |
### Target State
All principles should be ✅ COMPLIANT after Priority 1-2 fixes.
---
## Domain-Driven Design Compliance
### Current State
| DDD Concept | Status | Notes |
|-------------|--------|-------|
| **Bounded Contexts** | ⚠️ PARTIAL | Domains defined but boundaries unclear |
| **Entities** | ✅ GOOD | Present in Domain layer |
| **Value Objects** | ⚠️ PARTIAL | Some present, but inconsistent usage |
| **Aggregates** | ❌ WEAK | Missing proper aggregate roots |
| **Domain Events** | ⚠️ PARTIAL | Event system exists, but underutilized |
| **Repositories** | ✅ GOOD | Repository pattern implemented |
| **Domain Services** | ⚠️ PARTIAL | Some present, but mixed with app services |
---
## Testing Implications
**Current Issues Affecting Testability**:
1. Domain depending on Framework makes unit testing harder
2. HTTP in Domain couples business logic to web layer
3. Thin Domain layer means less isolated business logic to test
**After Fixes**:
- ✅ Pure Domain layer → easy unit testing
- ✅ Clear boundaries → better integration testing
- ✅ Framework independence → faster test execution
---
## Migration Strategy
### Phase 1: Critical Fixes (Week 1-2)
- Move HTTP out of Domain
- Move DI to Infrastructure
- Fix Infrastructure nesting
- Update all imports and namespaces
### Phase 2: Standardization (Week 3-4)
- Standardize naming conventions
- Fix PSR-4 violations
- Extract app logic from Framework
### Phase 3: Strengthening (Month 2)
- Strengthen Domain layer
- Reduce Framework bloat
- Flatten deep nesting
### Phase 4: Optimization (Month 3+)
- Split large directories
- Improve bounded contexts
- Comprehensive documentation
---
## Success Metrics
**After Priority 1-2 Fixes**:
- ✅ Zero architectural violations
- ✅ All layers respect Dependency Rule
- ✅ PSR-4 compliance: 100%
- ✅ Framework layer: <60% of codebase
- ✅ Domain layer: >15% of codebase
**Target Architecture Grade**: A- (90%) after all phases
---
## Conclusion
**Current Grade**: C+ (75%) - Good foundation with critical flaws
**Key Strengths**:
- ✅ Layer separation attempted
- ✅ Repository pattern implemented
- ✅ Value Objects used (though inconsistently)
- ✅ Event system in place
- ✅ Clear directory structure
**Critical Weaknesses**:
- ❌ HTTP in Domain layer
- ❌ DI setup in Domain layer
- ❌ Infrastructure nested in Application
- ❌ Framework layer too large (85%)
- ❌ Domain layer too thin (4%)
**Recommendation**: Implement Priority 1 fixes immediately to resolve critical architectural violations. Then proceed with Priority 2-3 fixes to achieve proper Clean Architecture and DDD compliance.
**Estimated Total Effort**: 2-3 months for complete restructuring
---
**Analysis Methodology**: Automated codebase exploration using framework's Discovery System, manual architectural review, Clean Architecture and DDD principles assessment.
**Tools Used**:
- Framework's `UnifiedDiscoveryService`
- Custom architectural analysis scripts
- PSR-4 compliance checker
**Next Steps**:
1. Review this analysis with development team
2. Create GitHub issues for Priority 1 fixes
3. Establish migration timeline
4. Update CI/CD to enforce new structure

76
docs/claude/README.md Normal file
View File

@@ -0,0 +1,76 @@
# Claude Documentation
Dieses Verzeichnis enthält AI-spezifische Dokumentation für Claude Code und andere AI-Agenten, die mit dem Framework arbeiten.
## Zweck
Die Dokumentation in diesem Verzeichnis ist speziell für AI-Agenten (wie Claude Code, Cursor AI, etc.) konzipiert und enthält:
- Framework-spezifische Kontexte und Personas
- MCP (Model Context Protocol) Integration
- Development Commands für AI-Agenten
- Coding Guidelines für AI-generierten Code
- Code-Generierungs-Beispiele
## Allgemeine Framework-Dokumentation
Für allgemeine Framework-Dokumentation, die sowohl für Entwickler als auch AI-Agenten relevant ist, siehe:
- [Framework Dokumentation](../README.md) - Hauptdokumentation
- [Features](../features/) - Feature-spezifische Dokumentation
- [Guides](../guides/) - Entwickleranleitungen
- [LiveComponents](../livecomponents/) - LiveComponents Dokumentation
## Wichtige Dokumentationen
### MCP Integration
- [MCP Integration](mcp-integration.md) - Model Context Protocol Server und Tools
### Framework Personas
- [Framework Personas](framework-personas.md) - AI Personas für Framework-Entwicklung
### Development Commands
- [Development Commands](development-commands.md) - Claude Code Commands und Workflows
### Coding Guidelines
- [Guidelines](guidelines.md) - AI Coding Guidelines und Best Practices
- [Architecture](architecture.md) - Framework-Architektur für AI-Agenten
- [Naming Conventions](naming-conventions.md) - Namenskonventionen
### Code Generation Examples
- [Examples](examples/) - Code-Generierungs-Beispiele
## Weitere AI-spezifische Dokumentationen
- [Performance Profiling](performance-profiling.md) - Performance-Analyse für AI-Agenten
- [Structured Logging](structured-logging.md) - Logging-Patterns
- [PHP 8.5 Integration](php85-framework-integration.md) - PHP 8.5 Features
- [PostgreSQL Features](postgresql-features.md) - PostgreSQL-spezifische Features
- [SSE System](sse-system.md) - Server-Sent Events
- [SSE Integration Guide](sse-integration-guide.md) - SSE Integration
- [Sockets Module](sockets-module.md) - Socket-Kommunikation
- [Magic Links System](magiclinks-system.md) - Magic Links Implementation
- [View Caching System](view-caching-system.md) - View-Caching
- [View Refactoring Plan](view-refactoring-plan.md) - View-Refactoring
- [X-Component Syntax](x-component-syntax.md) - X-Component Template Syntax
- [XComponent Processor](xcomponent-processor.md) - XComponent Processing
- [Animation System](animationsystem.md) - Animation Framework
- [Chips & Cookies](chips-cookies.md) - Cookie Management
- [Curl OOP API](curl-oop-api.md) - HTTP Client API
- [Deployment Architecture](deployment-architecture.md) - Deployment-Architektur
- [ML Framework Architecture](ml-framework-architecture.md) - Machine Learning Framework
- [POSIX System](posix-system.md) - POSIX-Integration
- [Typed String System](typed-string-system.md) - Typed String Value Objects
- [Framework Refactoring Recommendations](framework-refactoring-recommendations.md) - Refactoring-Empfehlungen
## Verwendung
Diese Dokumentation wird automatisch von AI-Agenten verwendet, die mit dem Framework arbeiten. Sie sollte nicht manuell bearbeitet werden, es sei denn, es handelt sich um AI-spezifische Kontexte oder Beispiele.
## Migration
Viele Dokumentationen wurden von diesem Verzeichnis in die allgemeine Dokumentationsstruktur migriert:
- Feature-Dokumentationen → `docs/features/`
- Guides → `docs/guides/`
- LiveComponents → `docs/livecomponents/`
Siehe [Dokumentationsanalyse](../DOCUMENTATION-ANALYSIS.md) für Details zur Reorganisation.

View File

@@ -0,0 +1,585 @@
# Animationssystem für Console-Modul
## Übersicht
Das Animationssystem bietet eine umfassende Lösung für Animationen im Console-Modul. Es unterstützt sowohl UI-Elemente in der TUI als auch Text-Animationen im Console-Output. Das System ist modular aufgebaut, erweiterbar und vollständig in den EventLoop integriert.
## Features
- **Mehrere Animationstypen**: Fade-In/Out, Slide, Typewriter, Marquee, Pulse
- **Keyframe-basierte Animationen**: Komplexe Animationen mit Easing-Functions
- **Composite Animationen**: Kombination mehrerer Animationen (parallel oder sequenziell)
- **EventLoop Integration**: Automatische Updates im Render-Loop
- **TUI & Console-Output**: Unterstützung für beide Anwendungsfälle
- **Factory & Builder Pattern**: Einfache Erstellung von Animationen
## Architektur
### Core-Komponenten
#### Animation Interface
Basis-Interface für alle Animationen:
```php
interface Animation
{
public function start(): void;
public function stop(): void;
public function pause(): void;
public function resume(): void;
public function update(float $deltaTime): bool;
public function isActive(): bool;
public function getProgress(): float;
public function getDuration(): float;
public function getDelay(): float;
public function isLooping(): bool;
public function onStart(callable $callback): self;
public function onComplete(callable $callback): self;
public function onPause(callable $callback): self;
public function onResume(callable $callback): self;
}
```
#### AnimationManager
Verwaltet mehrere Animationen gleichzeitig und aktualisiert sie automatisch:
```php
$animationManager = new AnimationManager();
// Animation hinzufügen
$animationManager->add($animation);
// Animationen aktualisieren (wird automatisch vom EventLoop aufgerufen)
$animationManager->update($deltaTime);
// Animation entfernen
$animationManager->remove($animation);
// Alle Animationen löschen
$animationManager->clear();
```
#### Easing Functions
Unterstützte Easing-Functions:
- `LINEAR` - Lineare Interpolation
- `EASE_IN` - Langsam starten
- `EASE_OUT` - Langsam enden
- `EASE_IN_OUT` - Langsam starten und enden
- `EASE_IN_QUAD` - Quadratische Beschleunigung
- `EASE_OUT_QUAD` - Quadratische Verzögerung
- `EASE_IN_OUT_QUAD` - Quadratische Beschleunigung und Verzögerung
- `BOUNCE` - Bounce-Effekt
- `ELASTIC` - Elastischer Effekt
## Animation-Typen
### FadeAnimation
Fade-In/Out Effekte für Text oder UI-Elemente:
```php
use App\Framework\Console\Animation\AnimationFactory;
use App\Framework\Console\Animation\EasingFunction;
// Fade-In
$fadeIn = AnimationFactory::fadeIn(1.0, EasingFunction::EASE_IN);
// Fade-Out
$fadeOut = AnimationFactory::fadeOut(1.0, EasingFunction::EASE_OUT);
// Custom Fade
$fade = AnimationFactory::fade(
duration: 2.0,
startOpacity: 0.0,
endOpacity: 1.0,
easing: EasingFunction::EASE_IN_OUT
);
```
### SlideAnimation
Slide-Effekte in verschiedene Richtungen:
```php
use App\Framework\Console\Animation\Types\SlideDirection;
// Von links
$slideFromLeft = AnimationFactory::slideInFromLeft(
distance: 20,
duration: 1.0
);
// Von rechts
$slideFromRight = AnimationFactory::slideInFromRight(
distance: 20,
duration: 1.0
);
// Custom Slide
$slide = AnimationFactory::slide(
direction: SlideDirection::UP,
distance: 10,
duration: 0.5,
easing: EasingFunction::EASE_OUT
);
```
### TypewriterAnimation
Typewriter-Effekt für Text:
```php
$typewriter = AnimationFactory::typewriter(
text: 'Hello, this is a typewriter animation!',
charactersPerSecond: 10.0
);
// Schnell
$fast = AnimationFactory::typewriter('Fast text', 20.0);
// Langsam
$slow = AnimationFactory::typewriter('Slow text', 5.0);
```
### MarqueeAnimation
Scrolling Text (Marquee):
```php
$marquee = AnimationFactory::marquee(
text: 'This is a scrolling marquee text',
width: 80,
speed: 1.0,
loop: true
);
// Schnell
$fastMarquee = AnimationFactory::marquee('Fast scrolling', 50, 5.0);
// Langsam
$slowMarquee = AnimationFactory::marquee('Slow scrolling', 50, 0.5);
```
### PulseAnimation
Pulsing-Effekte für Hervorhebungen:
```php
$pulse = AnimationFactory::pulse(
duration: 1.0,
scaleStart: 1.0,
scaleEnd: 1.2,
pulseSpeed: 2.0
);
// Sanft
$gentle = PulseAnimation::gentle(2.0);
// Stark
$strong = PulseAnimation::strong(1.0);
```
### KeyframeAnimation
Keyframe-basierte Animationen mit komplexen Interpolationen:
```php
use App\Framework\Console\Animation\AnimationFrame;
$keyframes = [
new AnimationFrame(0.0, 0, EasingFunction::EASE_IN),
new AnimationFrame(0.5, 100, EasingFunction::EASE_IN_OUT),
new AnimationFrame(1.0, 200, EasingFunction::EASE_OUT),
];
$keyframeAnimation = AnimationFactory::keyframe(
keyframes: $keyframes,
duration: 2.0,
loop: false
);
```
### CompositeAnimation
Kombination mehrerer Animationen:
```php
use App\Framework\Console\Animation\CompositeAnimation;
use App\Framework\Console\Animation\SequenceType;
$fadeIn = AnimationFactory::fadeIn(0.5);
$slide = AnimationFactory::slideInFromLeft(20, 0.5);
// Parallel (gleichzeitig)
$parallel = new CompositeAnimation(
animations: [$fadeIn, $slide],
sequenceType: SequenceType::PARALLEL,
loop: false
);
// Sequenziell (nacheinander)
$sequential = new CompositeAnimation(
animations: [$fadeIn, $slide],
sequenceType: SequenceType::SEQUENTIAL,
loop: false
);
```
### SpinnerAnimation
Animation-basierter Spinner:
```php
use App\Framework\Console\Animation\Types\SpinnerAnimation;
use App\Framework\Console\SpinnerStyle;
$spinner = AnimationFactory::spinner(
frames: SpinnerStyle::DOTS,
message: 'Loading...',
frameInterval: 0.1
);
// Oder direkt
$spinner = SpinnerAnimation::fromStyle(
style: SpinnerStyle::BARS,
message: 'Processing...',
frameInterval: 0.1
);
```
## Verwendung in Console-Output
### Einfache Text-Animationen
```php
use App\Framework\Console\ConsoleOutput;
$output = new ConsoleOutput();
// Fade-In
$output->animateFadeIn('Hello World!', 1.0);
// Fade-Out
$output->animateFadeOut('Goodbye!', 1.0);
// Typewriter
$output->animateTypewriter('This appears character by character', 10.0);
// Marquee
$output->animateMarquee('Scrolling text', 80, 1.0);
// Custom Animation
$customAnimation = AnimationFactory::fadeIn(2.0);
$output->animateText('Custom animated text', $customAnimation);
// Animationen aktualisieren
$output->updateAnimations(0.016); // ~60 FPS
```
### Animation Manager Zugriff
```php
$animationManager = $output->getAnimationManager();
// Animationen direkt hinzufügen
$animationManager->add($animation);
// Animationen aktualisieren
$animationManager->update($deltaTime);
```
## Verwendung in TUI
### TuiAnimationRenderer
```php
use App\Framework\Console\Animation\TuiAnimationRenderer;
use App\Framework\Console\Animation\AnimationFactory;
use App\Framework\Console\Animation\Types\SlideDirection;
$animationRenderer = $tuiRenderer->getAnimationRenderer();
if ($animationRenderer !== null) {
// Element animieren
$animationRenderer->fadeInElement('menu-item-1', 0.5);
$animationRenderer->slideInElement(
'button-1',
SlideDirection::LEFT,
20,
0.5
);
$animationRenderer->pulseElement('highlight-1', 1.0);
// Custom Animation
$customAnimation = AnimationFactory::fadeIn(1.0);
$animationRenderer->animateElement('element-id', $customAnimation);
// Animation stoppen
$animationRenderer->stopElement('element-id');
// Animationswerte abrufen
$opacity = $animationRenderer->getElementOpacity('element-id');
$position = $animationRenderer->getElementPosition('element-id');
$scale = $animationRenderer->getElementScale('element-id');
}
```
### Integration in TuiRenderer
Der `TuiRenderer` aktualisiert Animationen automatisch im Render-Loop:
```php
// In TuiRenderer::render()
if ($this->animationRenderer !== null) {
$this->animationRenderer->update(0.016); // ~60 FPS
}
```
## Factory & Builder Pattern
### AnimationFactory
Einfache Erstellung von Animationen:
```php
use App\Framework\Console\Animation\AnimationFactory;
$fadeIn = AnimationFactory::fadeIn(1.0);
$fadeOut = AnimationFactory::fadeOut(1.0);
$slide = AnimationFactory::slideInFromLeft(20, 1.0);
$typewriter = AnimationFactory::typewriter('Text', 10.0);
$marquee = AnimationFactory::marquee('Text', 80, 1.0);
$pulse = AnimationFactory::pulse(1.0);
$spinner = AnimationFactory::spinner(SpinnerStyle::DOTS, 'Loading...');
$keyframe = AnimationFactory::keyframe($keyframes, 2.0);
```
### AnimationBuilder
Fluent Builder für komplexe Konfigurationen:
```php
use App\Framework\Console\Animation\AnimationBuilder;
$animation = AnimationBuilder::fade(0.0, 1.0)
->duration(2.0)
->delay(0.5)
->loop(false)
->easing(EasingFunction::EASE_IN_OUT)
->onStart(function ($anim) {
echo "Animation started\n";
})
->onComplete(function ($anim) {
echo "Animation completed\n";
})
->onPause(function ($anim) {
echo "Animation paused\n";
})
->onResume(function ($anim) {
echo "Animation resumed\n";
})
->build();
```
## EventLoop Integration
Der `EventLoop` kann automatisch Animationen aktualisieren:
```php
use App\Framework\Console\Components\EventLoop\EventLoop;
use App\Framework\Console\Components\EventLoop\EventLoopConfig;
use App\Framework\Console\Animation\AnimationManager;
$animationManager = new AnimationManager();
$eventBuffer = new EventBuffer();
$config = new EventLoopConfig();
// EventLoop mit AnimationManager erstellen
$eventLoop = new EventLoop($eventBuffer, $config, $animationManager);
// Animationen werden automatisch aktualisiert
// Oder manuell:
$eventLoop->updateAnimations(0.016);
```
## Callbacks
Animationen unterstützen Callbacks für verschiedene Events:
```php
$animation = AnimationFactory::fadeIn(1.0)
->onStart(function (Animation $anim) {
echo "Animation started\n";
})
->onComplete(function (Animation $anim) {
echo "Animation completed\n";
})
->onPause(function (Animation $anim) {
echo "Animation paused\n";
})
->onResume(function (Animation $anim) {
echo "Animation resumed\n";
});
```
## Best Practices
### Performance
1. **Animation Manager wiederverwenden**: Erstellen Sie einen `AnimationManager` pro Anwendung und verwenden Sie ihn für alle Animationen.
2. **Animationen entfernen**: Entfernen Sie abgeschlossene Animationen, um Speicher zu sparen:
```php
$animation->onComplete(function ($anim) use ($manager) {
$manager->remove($anim);
});
```
3. **Update-Frequenz**: Aktualisieren Sie Animationen mit ~60 FPS (0.016 Sekunden):
```php
$animationManager->update(0.016);
```
### Code-Organisation
1. **Factory verwenden**: Verwenden Sie `AnimationFactory` für einfache Animationen statt direkte Instanziierung.
2. **Builder für komplexe Animationen**: Verwenden Sie `AnimationBuilder` für komplexe Konfigurationen.
3. **Keyframes für komplexe Animationen**: Verwenden Sie `KeyframeAnimation` für komplexe Animationen mit mehreren Zuständen.
### Fehlerbehandlung
```php
try {
$animation = AnimationFactory::fadeIn(1.0);
$animationManager->add($animation);
$animation->start();
} catch (\InvalidArgumentException $e) {
// Handle invalid animation parameters
error_log("Animation error: " . $e->getMessage());
}
```
## Beispiel: Demo Command
Ein vollständiges Beispiel finden Sie in:
`src/Framework/Console/Examples/AnimationDemoCommand.php`
Ausführen mit:
```bash
php console.php demo:animation
```
## Erweiterung
### Neue Animation-Typen hinzufügen
1. Erstellen Sie eine neue Klasse in `src/Framework/Console/Animation/Types/`
2. Implementieren Sie das `Animation` Interface oder erweitern Sie `BaseAnimation`
3. Implementieren Sie `updateAnimation(float $progress)` und `getCurrentValue()`
4. Fügen Sie Factory-Methoden zu `AnimationFactory` hinzu
Beispiel:
```php
final class CustomAnimation extends BaseAnimation
{
protected function updateAnimation(float $progress): void
{
// Custom animation logic
}
public function getCurrentValue(): mixed
{
// Return current animated value
}
}
```
## API-Referenz
### Animation Interface
- `start(): void` - Startet die Animation
- `stop(): void` - Stoppt die Animation
- `pause(): void` - Pausiert die Animation
- `resume(): void` - Setzt die Animation fort
- `update(float $deltaTime): bool` - Aktualisiert die Animation
- `isActive(): bool` - Prüft ob Animation aktiv ist
- `getProgress(): float` - Gibt Fortschritt zurück (0.0-1.0)
- `getDuration(): float` - Gibt Dauer zurück
- `getDelay(): float` - Gibt Verzögerung zurück
- `isLooping(): bool` - Prüft ob Animation loopt
- `onStart(callable $callback): self` - Setzt Start-Callback
- `onComplete(callable $callback): self` - Setzt Complete-Callback
- `onPause(callable $callback): self` - Setzt Pause-Callback
- `onResume(callable $callback): self` - Setzt Resume-Callback
### AnimationManager
- `add(Animation $animation): void` - Fügt Animation hinzu
- `remove(Animation $animation): void` - Entfernt Animation
- `update(float $deltaTime): void` - Aktualisiert alle Animationen
- `clear(): void` - Löscht alle Animationen
- `getActiveAnimations(): array` - Gibt aktive Animationen zurück
- `getActiveCount(): int` - Gibt Anzahl aktiver Animationen zurück
- `getTotalCount(): int` - Gibt Gesamtanzahl zurück
### ConsoleOutput
- `animateFadeIn(string $text, float $duration = 1.0): void`
- `animateFadeOut(string $text, float $duration = 1.0): void`
- `animateTypewriter(string $text, float $charactersPerSecond = 10.0): void`
- `animateMarquee(string $text, int $width = 80, float $speed = 1.0): void`
- `animateText(string $text, Animation $animation): void`
- `updateAnimations(float $deltaTime = 0.016): void`
- `getAnimationManager(): AnimationManager`
### TuiAnimationRenderer
- `animateElement(string $elementId, Animation $animation): void`
- `fadeInElement(string $elementId, float $duration = 0.5): void`
- `fadeOutElement(string $elementId, float $duration = 0.5): void`
- `pulseElement(string $elementId, float $duration = 1.0): void`
- `slideInElement(string $elementId, SlideDirection $direction, int $distance, float $duration = 0.5): void`
- `stopElement(string $elementId): void`
- `getElementOpacity(string $elementId): float`
- `getElementPosition(string $elementId): int`
- `getElementScale(string $elementId): float`
- `hasAnimation(string $elementId): bool`
- `update(float $deltaTime): void`
- `clear(): void`
## Troubleshooting
### Animationen laufen nicht
1. **AnimationManager prüfen**: Stellen Sie sicher, dass ein `AnimationManager` vorhanden ist.
2. **Update-Aufrufe**: Stellen Sie sicher, dass `update()` regelmäßig aufgerufen wird.
3. **Animation starten**: Rufen Sie `start()` auf der Animation auf.
### Performance-Probleme
1. **Zu viele Animationen**: Reduzieren Sie die Anzahl gleichzeitiger Animationen.
2. **Update-Frequenz**: Erhöhen Sie das Update-Intervall (z.B. 0.033 für 30 FPS).
3. **Abgeschlossene Animationen**: Entfernen Sie abgeschlossene Animationen.
### Animationen werden nicht angezeigt
1. **TUI-Integration**: Für TUI-Animationen muss `TuiAnimationRenderer` verwendet werden.
2. **Console-Output**: Für Text-Animationen muss `ConsoleOutput::animateText()` verwendet werden.
3. **Update-Loop**: Stellen Sie sicher, dass der Update-Loop läuft.
## Weitere Ressourcen
- **Plan-Dokument**: `console-modul-refactoring.plan.md`
- **Demo Command**: `src/Framework/Console/Examples/AnimationDemoCommand.php`
- **Framework Guidelines**: `docs/claude/guidelines.md`

View File

@@ -1,249 +0,0 @@
# Error Handling & Debugging
This guide covers error handling patterns and debugging strategies in the framework.
## Exception Handling
All custom exceptions in the framework must extend `FrameworkException` to ensure consistent error handling, logging, and recovery mechanisms.
### The FrameworkException System
The framework provides a sophisticated exception system with:
- **ExceptionContext**: Rich context information for debugging
- **ErrorCode**: Categorized error codes with recovery hints
- **RetryAfter**: Support for recoverable operations
- **Fluent Interface**: Easy context building
### Creating Custom Exceptions
```php
namespace App\Domain\User\Exceptions;
use App\Framework\Exception\FrameworkException;
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\ExceptionContext;
final class UserNotFoundException extends FrameworkException
{
public static function byId(UserId $id): self
{
return self::create(
DatabaseErrorCode::ENTITY_NOT_FOUND,
"User with ID '{$id->toString()}' not found"
)->withData([
'user_id' => $id->toString(),
'search_type' => 'by_id'
]);
}
public static function byEmail(Email $email): self
{
$context = ExceptionContext::forOperation('user.lookup', 'UserRepository')
->withData(['email' => $email->getMasked()]);
return self::fromContext(
"User with email not found",
$context,
DatabaseErrorCode::ENTITY_NOT_FOUND
);
}
}
```
### Using ErrorCode Enums
The framework provides category-specific error code enums for better organization and type safety:
```php
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\Core\AuthErrorCode;
use App\Framework\Exception\Core\HttpErrorCode;
use App\Framework\Exception\Core\SecurityErrorCode;
use App\Framework\Exception\Core\ValidationErrorCode;
// Database errors
DatabaseErrorCode::CONNECTION_FAILED
DatabaseErrorCode::QUERY_FAILED
DatabaseErrorCode::TRANSACTION_FAILED
DatabaseErrorCode::CONSTRAINT_VIOLATION
// Authentication errors
AuthErrorCode::CREDENTIALS_INVALID
AuthErrorCode::TOKEN_EXPIRED
AuthErrorCode::SESSION_EXPIRED
AuthErrorCode::ACCOUNT_LOCKED
// HTTP errors
HttpErrorCode::BAD_REQUEST
HttpErrorCode::NOT_FOUND
HttpErrorCode::METHOD_NOT_ALLOWED
HttpErrorCode::RATE_LIMIT_EXCEEDED
// Security errors
SecurityErrorCode::CSRF_TOKEN_INVALID
SecurityErrorCode::SQL_INJECTION_DETECTED
SecurityErrorCode::XSS_DETECTED
SecurityErrorCode::PATH_TRAVERSAL_DETECTED
// Validation errors
ValidationErrorCode::INVALID_INPUT
ValidationErrorCode::REQUIRED_FIELD_MISSING
ValidationErrorCode::BUSINESS_RULE_VIOLATION
ValidationErrorCode::INVALID_FORMAT
// Using error codes in exceptions:
throw FrameworkException::create(
DatabaseErrorCode::QUERY_FAILED,
"Failed to execute user query"
)->withContext(
ExceptionContext::forOperation('user.find', 'UserRepository')
->withData(['query' => 'SELECT * FROM users WHERE id = ?'])
->withDebug(['bind_params' => [$userId]])
);
```
### Exception Context Building
```php
// Method 1: Using factory methods
$exception = FrameworkException::forOperation(
'payment.process',
'PaymentService',
'Payment processing failed',
HttpErrorCode::BAD_GATEWAY
)->withData([
'amount' => $amount->toArray(),
'gateway' => 'stripe',
'customer_id' => $customerId
])->withMetadata([
'attempt' => 1,
'idempotency_key' => $idempotencyKey
]);
// Method 2: Building context separately
$context = ExceptionContext::empty()
->withOperation('order.validate', 'OrderService')
->withData([
'order_id' => $orderId,
'total' => $total->toDecimal()
])
->withDebug([
'validation_rules' => ['min_amount', 'max_items'],
'failed_rule' => 'min_amount'
]);
throw FrameworkException::fromContext(
'Order validation failed',
$context,
ValidationErrorCode::BUSINESS_RULE_VIOLATION
);
```
### Recoverable Exceptions
```php
// Creating recoverable exceptions with retry hints
final class RateLimitException extends FrameworkException
{
public static function exceeded(int $retryAfter): self
{
return self::create(
HttpErrorCode::RATE_LIMIT_EXCEEDED,
'API rate limit exceeded'
)->withRetryAfter($retryAfter)
->withData(['retry_after_seconds' => $retryAfter]);
}
}
// Using in code
try {
$response = $apiClient->request($endpoint);
} catch (RateLimitException $e) {
if ($e->isRecoverable()) {
$waitTime = $e->getRetryAfter();
// Schedule retry after $waitTime seconds
}
throw $e;
}
```
### Exception Categories
```php
// Check exception category for handling strategies
try {
$result = $operation->execute();
} catch (FrameworkException $e) {
if ($e->isCategory('AUTH')) {
// Handle authentication errors
return $this->redirectToLogin();
}
if ($e->isCategory('VAL')) {
// Handle validation errors
return $this->validationErrorResponse($e);
}
if ($e->isErrorCode(DatabaseErrorCode::CONNECTION_FAILED)) {
// Handle specific database connection errors
$this->notifyOps($e);
}
throw $e;
}
```
### Simple Exceptions for Quick Use
```php
// When you don't need the full context system
throw FrameworkException::simple('Quick error message');
// With previous exception
} catch (\PDOException $e) {
throw FrameworkException::simple(
'Database operation failed',
$e,
500
);
}
```
### Exception Data Sanitization
The framework automatically sanitizes sensitive data in exceptions:
```php
// Sensitive keys are automatically redacted
$exception->withData([
'username' => 'john@example.com',
'password' => 'secret123', // Will be logged as '[REDACTED]'
'api_key' => 'sk_live_...' // Will be logged as '[REDACTED]'
]);
```
### Best Practices
1. **Always extend FrameworkException** for custom exceptions
2. **Use ErrorCode enum** for categorizable errors
3. **Provide rich context** with operation, component, and data
4. **Use factory methods** for consistent exception creation
5. **Sanitize sensitive data** (automatic for common keys)
6. **Make exceptions domain-specific** (UserNotFoundException vs generic NotFoundException)
7. **Include recovery hints** for recoverable errors
## Logging Best Practices
TODO: Document logging patterns and levels
## Debug Strategies
TODO: Document debugging approaches and tools
## Error Recovery Patterns
TODO: Document error recovery and graceful degradation
## Common Error Scenarios
TODO: List common errors and solutions

View File

@@ -0,0 +1,735 @@
# JavaScript Modules Analysis & Recommendations
**Comprehensive Analysis of Existing JS Modules and Recommendations for New Modules and Refactorings**
This document provides a detailed analysis of the current JavaScript module ecosystem, identifies areas for improvement, and proposes new modules and refactorings.
---
## Table of Contents
1. [Current Module Overview](#current-module-overview)
2. [Module Quality Assessment](#module-quality-assessment)
3. [Recommended New Modules](#recommended-new-modules)
4. [Refactoring Recommendations](#refactoring-recommendations)
5. [Priority Matrix](#priority-matrix)
6. [Implementation Roadmap](#implementation-roadmap)
---
## Current Module Overview
### Module Categories
#### 1. **Core Framework Modules**
- `livecomponent/` - LiveComponents system (well-structured, modern)
- `ui/` - UI components (Modal, Dialog, Lightbox)
- `api-manager/` - Web API wrappers (comprehensive)
- `sse/` - Server-Sent Events client
#### 2. **Form & Input Modules**
- `form-handling/` - Form validation and submission
- `form-autosave.js` - Auto-save functionality
#### 3. **Navigation & Routing**
- `spa-router/` - Single Page Application router
#### 4. **Animation & Effects Modules**
- `canvas-animations/` - Canvas-based animations
- `scrollfx/` - Scroll-based animations
- `parallax/` - Parallax effects
- `smooth-scroll/` - Smooth scrolling
- `scroll-timeline/` - Scroll timeline animations
- `scroll-loop/` - Infinite scroll loops
- `scroll-dependent/` - Scroll-dependent effects
- `sticky-fade/` - Sticky fade effects
- `sticky-steps/` - Sticky step animations
- `inertia-scroll/` - Inertia scrolling
- `wheel-boost/` - Wheel boost effects
- `noise/` - Noise effects
#### 5. **Media & Image Modules**
- `image-manager/` - Image gallery, upload, modal
#### 6. **Utility Modules**
- `csrf-auto-refresh.js` - CSRF token management
- `hot-reload.js` - Hot reload functionality
- `performance-profiler/` - Performance profiling
- `webpush/` - Web Push notifications
#### 7. **Admin Modules**
- `admin/data-table.js` - Admin data tables
---
## Module Quality Assessment
### ✅ Well-Structured Modules (Keep as-is)
1. **livecomponent/** - Excellent structure, modern patterns
- ✅ Modular architecture
- ✅ TypeScript definitions
- ✅ Error handling
- ✅ Comprehensive documentation
2. **api-manager/** - Well-organized Web API wrappers
- ✅ Consistent API
- ✅ Feature detection
- ✅ Good separation of concerns
3. **form-handling/** - Solid form handling
- ✅ Clear separation (Handler, Validator, State)
- ✅ Progressive enhancement
- ⚠️ Could benefit from LiveComponent integration
4. **ui/** - Clean UI component system
- ✅ Reusable components
- ✅ Consistent API
- ⚠️ Could expand with more components
### ⚠️ Modules Needing Refactoring
1. **spa-router/** - Good but could be improved
- ⚠️ Mixed concerns (routing + transitions)
- ⚠️ Could better integrate with LiveComponents
- ⚠️ Module re-initialization could be cleaner
2. **form-autosave.js** - Standalone file
- ⚠️ Should be part of form-handling module
- ⚠️ No module system integration
3. **Scroll Animation Modules** - Too many separate modules
- ⚠️ `scrollfx/`, `parallax/`, `scroll-timeline/`, `scroll-loop/`, `scroll-dependent/`, `sticky-fade/`, `sticky-steps/` - Could be unified
- ⚠️ Duplicate functionality
- ⚠️ Inconsistent APIs
4. **image-manager/** - Good but could be enhanced
- ⚠️ Could integrate with LiveComponent file uploads
- ⚠️ EventEmitter pattern could be modernized
5. **performance-profiler/** - Standalone
- ⚠️ Could integrate with LiveComponent DevTools
- ⚠️ Should be part of development tools
### ❌ Modules Needing Major Refactoring
1. **Multiple Scroll Modules** - Consolidation needed
- ❌ 8+ separate scroll-related modules
- ❌ Inconsistent patterns
- ❌ Hard to maintain
2. **csrf-auto-refresh.js** - Standalone file
- ❌ Should be part of security module
- ❌ No module system integration
---
## Recommended New Modules
### 1. **State Management Module** (High Priority)
**Purpose**: Centralized state management for client-side state
**Features**:
- Reactive state store (similar to Redux/Vuex)
- State persistence (localStorage, sessionStorage)
- State synchronization across tabs
- Time-travel debugging
- Integration with LiveComponents
**Use Cases**:
- User preferences
- Shopping cart state
- UI state (sidebar open/closed, theme)
- Form drafts
**API Example**:
```javascript
import { StateManager } from './modules/state-manager/index.js';
const store = StateManager.create({
user: { name: '', email: '' },
cart: { items: [], total: 0 },
ui: { sidebarOpen: false }
});
// Reactive updates
store.subscribe('cart', (cart) => {
updateCartUI(cart);
});
// Actions
store.dispatch('cart.addItem', { id: 1, name: 'Product' });
```
**Priority**: High
**Effort**: Medium (2-3 days)
---
### 2. **Validation Module** (High Priority)
**Purpose**: Standalone validation system (not just forms)
**Features**:
- Field-level validation
- Schema-based validation (JSON Schema)
- Async validation
- Custom validation rules
- Integration with LiveComponents
- Integration with form-handling
**Use Cases**:
- Form validation
- API response validation
- User input validation
- Data transformation validation
**API Example**:
```javascript
import { Validator } from './modules/validation/index.js';
const validator = Validator.create({
email: {
type: 'email',
required: true,
message: 'Invalid email address'
},
age: {
type: 'number',
min: 18,
max: 100
}
});
const result = await validator.validate({ email: 'test@example.com', age: 25 });
```
**Priority**: High
**Effort**: Medium (2-3 days)
---
### 3. **Cache Manager Module** (Medium Priority)
**Purpose**: Intelligent caching for API responses and computed values
**Features**:
- Memory cache
- IndexedDB cache
- Cache invalidation strategies
- Cache warming
- Cache analytics
- Integration with RequestDeduplicator
**Use Cases**:
- API response caching
- Computed value caching
- Image caching
- Search result caching
**API Example**:
```javascript
import { CacheManager } from './modules/cache-manager/index.js';
const cache = CacheManager.create({
strategy: 'stale-while-revalidate',
ttl: 3600000 // 1 hour
});
// Cache API response
const data = await cache.get('users', async () => {
return await fetch('/api/users').then(r => r.json());
});
// Invalidate cache
cache.invalidate('users');
```
**Priority**: Medium
**Effort**: Medium (2-3 days)
---
### 4. **Event Bus Module** (Medium Priority)
**Purpose**: Centralized event system for cross-module communication
**Features**:
- Pub/sub pattern
- Namespaced events
- Event filtering
- Event history
- Integration with LiveComponents
- Integration with SSE
**Use Cases**:
- Component communication
- Module communication
- Global notifications
- Analytics events
**API Example**:
```javascript
import { EventBus } from './modules/event-bus/index.js';
const bus = EventBus.create();
// Subscribe
bus.on('user:logged-in', (user) => {
updateUI(user);
});
// Publish
bus.emit('user:logged-in', { id: 1, name: 'John' });
// Namespaced events
bus.on('livecomponent:action-executed', (data) => {
console.log('Action executed:', data);
});
```
**Priority**: Medium
**Effort**: Low (1-2 days)
---
### 5. **Storage Manager Module** (Low Priority)
**Purpose**: Unified storage interface (localStorage, sessionStorage, IndexedDB)
**Features**:
- Unified API for all storage types
- Automatic serialization
- Storage quotas
- Storage migration
- Storage analytics
**Note**: Partially exists in `api-manager/StorageManager`, but could be enhanced
**Priority**: Low (enhance existing)
**Effort**: Low (1 day)
---
### 6. **Router Enhancement Module** (Medium Priority)
**Purpose**: Enhanced routing with guards, middleware, and lazy loading
**Features**:
- Route guards (auth, permissions)
- Route middleware
- Lazy route loading
- Route transitions
- Route analytics
- Integration with LiveComponents
**API Example**:
```javascript
import { Router } from './modules/router/index.js';
const router = Router.create({
routes: [
{
path: '/dashboard',
component: 'DashboardComponent',
guard: 'auth',
middleware: ['analytics']
}
]
});
router.beforeEach((to, from, next) => {
if (requiresAuth(to) && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
```
**Priority**: Medium
**Effort**: Medium (2-3 days)
---
### 7. **Animation System Module** (Low Priority)
**Purpose**: Unified animation system consolidating all scroll/animation modules
**Features**:
- Unified animation API
- Scroll-based animations
- Timeline animations
- Performance optimizations
- Integration with Web Animations API
**Consolidates**:
- `scrollfx/`
- `parallax/`
- `scroll-timeline/`
- `scroll-loop/`
- `scroll-dependent/`
- `sticky-fade/`
- `sticky-steps/`
- `canvas-animations/`
**Priority**: Low (refactoring existing)
**Effort**: High (5-7 days)
---
### 8. **Error Tracking Module** (High Priority)
**Purpose**: Centralized error tracking and reporting
**Features**:
- Error collection
- Error grouping
- Error reporting (to backend)
- Error analytics
- Integration with ErrorBoundary
- Source map support
**API Example**:
```javascript
import { ErrorTracker } from './modules/error-tracking/index.js';
const tracker = ErrorTracker.create({
endpoint: '/api/errors',
sampleRate: 1.0
});
// Automatic error tracking
tracker.init();
// Manual error reporting
tracker.captureException(new Error('Something went wrong'), {
context: { userId: 123 },
tags: { feature: 'checkout' }
});
```
**Priority**: High
**Effort**: Medium (2-3 days)
---
### 9. **Analytics Module** (Medium Priority)
**Purpose**: Unified analytics system
**Features**:
- Event tracking
- Page view tracking
- User behavior tracking
- Custom events
- Integration with LiveComponents
- Privacy-compliant (GDPR)
**API Example**:
```javascript
import { Analytics } from './modules/analytics/index.js';
const analytics = Analytics.create({
providers: ['google-analytics', 'custom']
});
analytics.track('purchase', {
value: 99.99,
currency: 'EUR',
items: [{ id: 'product-1', quantity: 1 }]
});
```
**Priority**: Medium
**Effort**: Medium (2-3 days)
---
### 10. **Internationalization (i18n) Module** (Low Priority)
**Purpose**: Internationalization and localization
**Features**:
- Translation management
- Pluralization
- Date/time formatting
- Number formatting
- Currency formatting
- Integration with LiveComponents
**API Example**:
```javascript
import { i18n } from './modules/i18n/index.js';
i18n.init({
locale: 'de-DE',
fallback: 'en-US',
translations: {
'de-DE': { 'welcome': 'Willkommen' },
'en-US': { 'welcome': 'Welcome' }
}
});
const message = i18n.t('welcome');
```
**Priority**: Low
**Effort**: Medium (2-3 days)
---
## Refactoring Recommendations
### 1. **Consolidate Scroll Animation Modules** (High Priority)
**Current State**: 8+ separate scroll-related modules
**Proposed Solution**: Create unified `animation-system/` module
**Benefits**:
- Single API for all animations
- Reduced bundle size
- Easier maintenance
- Better performance
- Consistent patterns
**Implementation**:
1. Create `animation-system/` module
2. Migrate functionality from existing modules
3. Maintain backward compatibility during transition
4. Deprecate old modules
5. Update documentation
**Priority**: High
**Effort**: High (5-7 days)
---
### 2. **Integrate form-autosave into form-handling** (Medium Priority)
**Current State**: Standalone `form-autosave.js` file
**Proposed Solution**: Add autosave functionality to `form-handling/` module
**Benefits**:
- Better organization
- Shared form state
- Consistent API
- Easier maintenance
**Implementation**:
1. Move autosave logic into `FormHandler`
2. Add autosave configuration options
3. Integrate with `FormState`
4. Update documentation
**Priority**: Medium
**Effort**: Low (1 day)
---
### 3. **Enhance SPA Router with LiveComponent Integration** (Medium Priority)
**Current State**: SPA Router works independently
**Proposed Solution**: Better integration with LiveComponents
**Benefits**:
- Automatic LiveComponent initialization after navigation
- Better state management
- Improved performance
- Unified API
**Implementation**:
1. Add LiveComponent auto-initialization
2. Integrate with LiveComponentManager
3. Handle component state during navigation
4. Update documentation
**Priority**: Medium
**Effort**: Medium (2-3 days)
---
### 4. **Create Security Module** (Medium Priority)
**Current State**: `csrf-auto-refresh.js` is standalone
**Proposed Solution**: Create `security/` module
**Features**:
- CSRF token management
- XSS protection helpers
- Content Security Policy helpers
- Security headers validation
**Implementation**:
1. Create `security/` module
2. Move CSRF logic
3. Add additional security features
4. Update documentation
**Priority**: Medium
**Effort**: Low (1-2 days)
---
### 5. **Integrate Performance Profiler with DevTools** (Low Priority)
**Current State**: Standalone `performance-profiler/` module
**Proposed Solution**: Integrate with LiveComponent DevTools
**Benefits**:
- Unified developer experience
- Better visualization
- Easier debugging
- Reduced bundle size (dev only)
**Implementation**:
1. Move profiler into DevTools
2. Integrate with LiveComponent profiling
3. Update UI
4. Update documentation
**Priority**: Low
**Effort**: Medium (2-3 days)
---
### 6. **Modernize Image Manager** (Low Priority)
**Current State**: Uses EventEmitter pattern
**Proposed Solution**: Modernize with ES6 classes and better integration
**Benefits**:
- Modern patterns
- Better TypeScript support
- Integration with LiveComponent file uploads
- Improved performance
**Implementation**:
1. Refactor to ES6 classes
2. Add TypeScript definitions
3. Integrate with LiveComponent file uploads
4. Update documentation
**Priority**: Low
**Effort**: Medium (2-3 days)
---
## Priority Matrix
### High Priority (Implement Soon)
1. **State Management Module** - Needed for complex applications
2. **Validation Module** - Reusable validation logic
3. **Error Tracking Module** - Production debugging
4. **Consolidate Scroll Animation Modules** - Maintenance burden
### Medium Priority (Implement Next)
1. **Cache Manager Module** - Performance optimization
2. **Event Bus Module** - Cross-module communication
3. **Router Enhancement Module** - Better routing features
4. **Analytics Module** - Business requirements
5. **Integrate form-autosave** - Code organization
6. **Enhance SPA Router** - Better integration
7. **Create Security Module** - Security best practices
### Low Priority (Nice to Have)
1. **Storage Manager Module** - Enhance existing
2. **Animation System Module** - Refactoring existing
3. **i18n Module** - Internationalization
4. **Integrate Performance Profiler** - Developer experience
5. **Modernize Image Manager** - Code quality
---
## Implementation Roadmap
### Phase 1: Foundation (Weeks 1-2)
1. **State Management Module** (3 days)
2. **Validation Module** (3 days)
3. **Error Tracking Module** (3 days)
4. **Event Bus Module** (2 days)
**Total**: ~11 days
### Phase 2: Integration & Refactoring (Weeks 3-4)
1. **Integrate form-autosave** (1 day)
2. **Enhance SPA Router** (3 days)
3. **Create Security Module** (2 days)
4. **Cache Manager Module** (3 days)
**Total**: ~9 days
### Phase 3: Advanced Features (Weeks 5-6)
1. **Router Enhancement Module** (3 days)
2. **Analytics Module** (3 days)
3. **Consolidate Scroll Animation Modules** (7 days)
**Total**: ~13 days
### Phase 4: Polish & Optimization (Weeks 7-8)
1. **Storage Manager Enhancement** (1 day)
2. **Integrate Performance Profiler** (3 days)
3. **Modernize Image Manager** (3 days)
4. **Documentation updates** (2 days)
**Total**: ~9 days
---
## Module Architecture Principles
### 1. **Consistency**
- All modules should follow the same structure
- Consistent naming conventions
- Consistent API patterns
### 2. **Modularity**
- Modules should be independent
- Clear dependencies
- Easy to test in isolation
### 3. **Integration**
- Modules should integrate well with LiveComponents
- Shared configuration
- Unified event system
### 4. **Performance**
- Lazy loading where possible
- Tree-shaking support
- Minimal bundle size
### 5. **Developer Experience**
- TypeScript definitions
- Comprehensive documentation
- Clear error messages
- DevTools integration
---
## Next Steps
1. **Review this analysis** with the team
2. **Prioritize modules** based on project needs
3. **Create detailed implementation plans** for high-priority modules
4. **Start with Phase 1** (Foundation modules)
5. **Iterate and refine** based on feedback
---
**Last Updated**: 2025-01-XX
**Status**: Draft - Pending Review

View File

@@ -1,681 +0,0 @@
# LiveComponent Lazy Loading
**Performance-Optimization durch Viewport-basiertes Component Loading**
## Übersicht
Das Lazy Loading System lädt LiveComponents erst, wenn sie im Browser-Viewport sichtbar werden. Dies reduziert die initiale Ladezeit erheblich, besonders bei Seiten mit vielen Components.
**Key Features:**
-**Viewport-Detection** - Intersection Observer API
- 🎯 **Priority-Based Loading** - High/Normal/Low Prioritäten
- 🔄 **Progressive Loading** - Sequentielle Queue-Verarbeitung
- 📊 **Loading States** - Placeholder → Loading → Loaded
- 🧹 **Automatic Cleanup** - Memory-efficient observer management
## Performance Benefits
| Metric | Without Lazy Loading | With Lazy Loading | Improvement |
|--------|---------------------|-------------------|-------------|
| Initial Page Load | 2500ms | 800ms | **68% faster** |
| Time to Interactive | 3200ms | 1100ms | **66% faster** |
| Initial JavaScript | 450KB | 120KB | **73% smaller** |
| Components Loaded | All (20) | Visible (3-5) | **75% fewer** |
| Memory Usage | 120MB | 35MB | **71% less** |
## Quick Start
### 1. Basic Lazy Component
```html
<!-- Regular Component (loads immediately) -->
<div data-live-component="notification-center:user-123"
data-state='{"notifications": []}'
data-csrf-token="...">
<!-- Component HTML -->
</div>
<!-- Lazy Component (loads on viewport entry) -->
<div data-live-component-lazy="notification-center:user-123"
data-lazy-threshold="0.1"
data-lazy-priority="normal"
data-lazy-placeholder="Loading notifications...">
</div>
```
**Key Differences:**
- Use `data-live-component-lazy` instead of `data-live-component`
- No initial HTML needed (placeholder will be shown)
- No `data-state` needed initially (server will provide it)
### 2. Priority Levels
```html
<!-- High Priority - Loads first -->
<div data-live-component-lazy="user-stats:123"
data-lazy-priority="high"
data-lazy-placeholder="Loading user stats...">
</div>
<!-- Normal Priority - Standard loading (default) -->
<div data-live-component-lazy="activity-feed:user-123"
data-lazy-priority="normal"
data-lazy-placeholder="Loading activities...">
</div>
<!-- Low Priority - Loads last -->
<div data-live-component-lazy="recommendations:user-123"
data-lazy-priority="low"
data-lazy-placeholder="Loading recommendations...">
</div>
```
**Priority Weights:**
- `high`: 3 (Critical components, always load first)
- `normal`: 2 (Standard components, default)
- `low`: 1 (Non-critical components, load last)
## Configuration Options
### Viewport Threshold
Controls when loading triggers (0.0 = top edge, 1.0 = fully visible):
```html
<!-- Load when 10% visible (default) -->
<div data-live-component-lazy="counter:demo"
data-lazy-threshold="0.1">
</div>
<!-- Load when 50% visible -->
<div data-live-component-lazy="chart:demo"
data-lazy-threshold="0.5">
</div>
<!-- Load when fully visible -->
<div data-live-component-lazy="video-player:demo"
data-lazy-threshold="1.0">
</div>
```
### Root Margin (Pre-loading)
Global configuration in LazyComponentLoader:
```javascript
this.defaultOptions = {
rootMargin: '50px', // Load 50px before entering viewport
threshold: 0.1 // Default threshold
};
```
**Effect:** Components start loading before user scrolls to them, creating seamless experience.
### Custom Placeholder
```html
<!-- Simple text placeholder -->
<div data-live-component-lazy="notifications:123"
data-lazy-placeholder="Loading your notifications...">
</div>
<!-- No placeholder (just loading indicator) -->
<div data-live-component-lazy="stats:123">
</div>
```
## Loading States
The system automatically manages 3 loading states:
### 1. Placeholder State
Shown immediately when component is registered:
```html
<div class="livecomponent-lazy-placeholder">
<div></div>
<div>Loading notifications...</div>
</div>
```
### 2. Loading State
Shown when component enters viewport and server request starts:
```html
<div class="livecomponent-lazy-loading">
<div class="spinner"></div>
<div>Loading component...</div>
</div>
```
### 3. Loaded State
Component HTML from server replaces placeholder:
```html
<div data-live-component="notification-center:user-123" ...>
<!-- Full component HTML with actions, state, etc. -->
</div>
```
## Backend Implementation
### Controller Route
```php
#[Route('/live-component/{id}/lazy-load', method: Method::GET)]
public function handleLazyLoad(string $id, HttpRequest $request): JsonResult
{
try {
$componentId = ComponentId::fromString($id);
// Resolve component with initial state
$component = $this->componentRegistry->resolve(
$componentId,
initialData: null
);
// Render component HTML with wrapper
$html = $this->componentRegistry->renderWithWrapper($component);
// Get component state
$componentData = $component->getData();
// Generate CSRF token for component
$csrfToken = $this->componentRegistry->generateCsrfToken($componentId);
return new JsonResult([
'success' => true,
'html' => $html,
'state' => $componentData->toArray(),
'csrf_token' => $csrfToken,
'component_id' => $componentId->toString()
]);
} catch (\Exception $e) {
return new JsonResult([
'success' => false,
'error' => $e->getMessage(),
'error_code' => 'LAZY_LOAD_FAILED'
], Status::INTERNAL_SERVER_ERROR);
}
}
```
### Response Format
```json
{
"success": true,
"html": "<div data-live-component=\"notification-center:user-123\" ...>...</div>",
"state": {
"notifications": [...]
},
"csrf_token": "abc123...",
"component_id": "notification-center:user-123"
}
```
## JavaScript API
### LazyComponentLoader Class
```javascript
import { LazyComponentLoader } from './LazyComponentLoader.js';
// Create loader instance
const lazyLoader = new LazyComponentLoader(liveComponentManager);
// Initialize system (scans DOM for lazy components)
lazyLoader.init();
// Register new lazy component dynamically
lazyLoader.registerLazyComponent(element);
// Unregister lazy component
lazyLoader.unregister(element);
// Get loading statistics
const stats = lazyLoader.getStats();
console.log(stats);
// {
// total: 10,
// loaded: 3,
// loading: 1,
// pending: 6,
// queued: 2
// }
// Cleanup and destroy
lazyLoader.destroy();
```
### Events
Listen for lazy loading events:
```javascript
// Component successfully loaded
document.addEventListener('livecomponent:lazy:loaded', (e) => {
console.log('Loaded:', e.detail.componentId);
// Custom post-load logic
});
// Component load failed
document.addEventListener('livecomponent:lazy:error', (e) => {
console.error('Error:', e.detail.componentId, e.detail.error);
// Error handling, retry logic, etc.
});
```
### Manual Loading
```javascript
// Force load a specific component
const config = lazyLoader.lazyComponents.get(element);
if (config && !config.loaded) {
await lazyLoader.loadComponent(config);
}
// Process loading queue immediately (bypasses delays)
await lazyLoader.processLoadingQueue();
```
## Architecture
### Loading Flow
```
┌─────────────────┐
│ DOM Scan │
│ (init) │
└────────┬────────┘
┌─────────────────┐
│ Register Lazy │
│ Components │
└────────┬────────┘
┌─────────────────┐
│ Show Placeholder│
└────────┬────────┘
┌─────────────────┐
│ Start Observing │
│ (Intersection │
│ Observer) │
└────────┬────────┘
┌─────────────────┐ No
│ Intersecting? ├─────────► Continue Observing
└────────┬────────┘
│ Yes
┌─────────────────┐
│ Queue Component │
│ (Priority-based)│
└────────┬────────┘
┌─────────────────┐
│ Process Queue │
│ (Sequential) │
└────────┬────────┘
┌─────────────────┐
│ Show Loading │
└────────┬────────┘
┌─────────────────┐
│ Fetch from │
│ Server │
│ GET /lazy-load │
└────────┬────────┘
┌─────────────────┐
│ Replace HTML │
│ Initialize │
│ LiveComponent │
└────────┬────────┘
┌─────────────────┐
│ Stop Observing │
│ Mark as Loaded │
└─────────────────┘
```
### Priority Queue System
```javascript
// When component enters viewport
queueComponentLoad(config) {
const priorityWeight = this.getPriorityWeight(config.priority);
this.loadingQueue.push({
config,
priority: priorityWeight,
timestamp: Date.now()
});
// Sort by priority (high to low), then timestamp (early to late)
this.loadingQueue.sort((a, b) => {
if (b.priority !== a.priority) {
return b.priority - a.priority;
}
return a.timestamp - b.timestamp;
});
this.processLoadingQueue();
}
```
**Queue Order Example:**
```
Queue: [
{ priority: 3, timestamp: 1000 }, // High, entered first
{ priority: 3, timestamp: 1100 }, // High, entered second
{ priority: 2, timestamp: 900 }, // Normal, entered early
{ priority: 1, timestamp: 1200 } // Low, entered last
]
```
## Use Cases
### 1. Long Landing Pages
```html
<!-- Above the fold - immediate -->
<div data-live-component="hero:banner">...</div>
<div data-live-component="features:overview">...</div>
<!-- Below the fold - lazy -->
<div data-live-component-lazy="testimonials:featured"
data-lazy-priority="normal">
</div>
<div data-live-component-lazy="pricing:table"
data-lazy-priority="low">
</div>
<div data-live-component-lazy="faq:list"
data-lazy-priority="low">
</div>
```
### 2. Dashboard with Widgets
```html
<!-- Critical widgets - high priority -->
<div data-live-component-lazy="user-stats:123"
data-lazy-priority="high"
data-lazy-threshold="0.1">
</div>
<div data-live-component-lazy="notifications:123"
data-lazy-priority="high"
data-lazy-threshold="0.1">
</div>
<!-- Secondary widgets - normal priority -->
<div data-live-component-lazy="activity-feed:123"
data-lazy-priority="normal">
</div>
<!-- Tertiary widgets - low priority -->
<div data-live-component-lazy="recommendations:123"
data-lazy-priority="low">
</div>
```
### 3. Infinite Scroll
```html
<!-- Initial visible items -->
<div data-live-component="product-card:1">...</div>
<div data-live-component="product-card:2">...</div>
<div data-live-component="product-card:3">...</div>
<!-- Lazy load next batch -->
<div data-live-component-lazy="product-card:4"
data-lazy-threshold="0.5">
</div>
<div data-live-component-lazy="product-card:5"
data-lazy-threshold="0.5">
</div>
```
### 4. Tab Panels
```html
<div class="tabs">
<!-- Active tab - immediate -->
<div class="tab-panel active">
<div data-live-component="profile:user-123">...</div>
</div>
<!-- Hidden tabs - lazy load when shown -->
<div class="tab-panel">
<div data-live-component-lazy="settings:user-123"
data-lazy-priority="normal">
</div>
</div>
<div class="tab-panel">
<div data-live-component-lazy="activity-history:user-123"
data-lazy-priority="low">
</div>
</div>
</div>
```
## Best Practices
### ✅ DO
**Use lazy loading for:**
- Below-the-fold components
- Secondary/tertiary content
- Heavy components (charts, tables, media)
- Non-critical features
- Infrequently accessed sections
**Priority Guidelines:**
- `high`: User-specific data, real-time updates
- `normal`: Standard content, common features
- `low`: Recommendations, suggestions, ads
**Threshold Guidelines:**
- `0.1`: Standard (load early for smooth UX)
- `0.5`: Conservative (load when half-visible)
- `1.0`: Aggressive (only when fully visible)
### ❌ DON'T
**Avoid lazy loading for:**
- Above-the-fold content
- Critical user interactions
- SEO-important content
- Small/lightweight components
**Anti-patterns:**
- Setting all components to `high` priority
- Using threshold `1.0` for everything
- Lazy loading components user immediately needs
- Over-complicating with too many priority levels
## Performance Optimization
### Server-Side
```php
// Cache component HTML for repeated lazy loads
public function handleLazyLoad(string $id): JsonResult
{
$cacheKey = "lazy_component_{$id}";
return $this->cache->remember($cacheKey, function() use ($id) {
$component = $this->componentRegistry->resolve(
ComponentId::fromString($id)
);
return new JsonResult([
'success' => true,
'html' => $this->componentRegistry->renderWithWrapper($component),
// ... other data
]);
}, Duration::fromMinutes(5));
}
```
### Client-Side
```javascript
// Adjust root margin for faster pre-loading
this.defaultOptions = {
rootMargin: '200px', // Start loading 200px early
threshold: 0.1
};
// Batch multiple components entering viewport simultaneously
// (Already implemented in processLoadingQueue)
```
## Troubleshooting
### Component doesn't load
**Check:**
1. `data-live-component-lazy` attribute present?
2. LazyLoader initialized? (`window.LiveComponent.lazyLoader`)
3. Element visible in viewport?
4. Network request succeeding? (check DevTools)
5. Server route `/live-component/{id}/lazy-load` working?
**Debug:**
```javascript
const stats = window.LiveComponent.lazyLoader.getStats();
console.log(stats); // Check pending/loading/loaded counts
// Check if component is registered
const config = window.LiveComponent.lazyLoader.lazyComponents.get(element);
console.log(config);
```
### Component loads too late/early
**Adjust threshold:**
```html
<!-- Load earlier (when 10% visible instead of 50%) -->
<div data-live-component-lazy="..."
data-lazy-threshold="0.1">
</div>
```
**Adjust root margin:**
```javascript
// Global configuration
this.defaultOptions.rootMargin = '100px'; // Load 100px before viewport
```
### Priority not working
**Check queue:**
```javascript
console.log(window.LiveComponent.lazyLoader.loadingQueue);
// Should be sorted by priority (high to low)
```
**Verify priority value:**
```html
<div data-lazy-priority="high"> ✅ Correct
<div data-lazy-priority="High"> ❌ Case-sensitive!
<div data-lazy-priority="urgent"> ❌ Only high/normal/low
```
## Testing
### Manual Testing
```bash
# Open test page in browser
php tests/debug/test-lazy-loading.php
# Navigate to http://localhost/tests/debug/test-lazy-loading.php
```
**Test Checklist:**
- [ ] Placeholders shown immediately
- [ ] Components load when scrolling into view
- [ ] High priority loads before low priority
- [ ] Loading spinner appears briefly
- [ ] Stats panel updates correctly
- [ ] Console logs show loading sequence
- [ ] No console errors
### Automated Testing
```javascript
describe('LazyComponentLoader', () => {
it('registers lazy components', () => {
const loader = new LazyComponentLoader(mockManager);
loader.init();
const lazyElements = document.querySelectorAll('[data-live-component-lazy]');
expect(loader.lazyComponents.size).toBe(lazyElements.length);
});
it('loads component on intersection', async () => {
const loader = new LazyComponentLoader(mockManager);
loader.init();
// Simulate intersection
const entry = { isIntersecting: true, target: lazyElement };
loader.handleIntersection([entry]);
// Wait for load
await new Promise(resolve => setTimeout(resolve, 100));
const config = loader.lazyComponents.get(lazyElement);
expect(config.loaded).toBe(true);
});
it('respects priority ordering', () => {
const loader = new LazyComponentLoader(mockManager);
loader.queueComponentLoad({ priority: 'low', ...lowConfig });
loader.queueComponentLoad({ priority: 'high', ...highConfig });
loader.queueComponentLoad({ priority: 'normal', ...normalConfig });
expect(loader.loadingQueue[0].config).toBe(highConfig);
expect(loader.loadingQueue[1].config).toBe(normalConfig);
expect(loader.loadingQueue[2].config).toBe(lowConfig);
});
});
```
## Summary
**Lazy Loading provides:**
-**68% faster** initial page load
-**73% smaller** initial JavaScript bundle
-**75% fewer** components loaded initially
-**71% less** memory usage
-**Seamless UX** with priority-based loading
-**Easy integration** with minimal code changes
**When to use:**
- Pages with 10+ components
- Below-the-fold content
- Heavy components (charts, tables, media)
- Secondary/tertiary features
**Implementation effort:****Low** - Just change `data-live-component` to `data-live-component-lazy`

1316
docs/claude/posix-system.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,671 @@
# Sockets Module Documentation
## Übersicht
Das Sockets-Modul (`src/Framework/Sockets/`) bietet eine vollständige, type-safe Abstraktion über PHP's Socket-Erweiterung. Es ermöglicht:
- **Type-safe Socket-Operationen**: Alle Socket-Operationen verwenden Value Objects statt primitiver Typen
- **TCP/UDP Server & Client**: Vollständige Server- und Client-Implementierung
- **Unix Domain Sockets**: Unterstützung für Unix Domain Sockets
- **PCNTL Integration**: Socket-Server in geforkten Worker-Prozessen
- **Async Integration**: Non-blocking Socket I/O mit Fibers
- **Connection Pooling**: Automatisches Management von Socket-Verbindungen
## Architektur
### Modulstruktur
```
src/Framework/Sockets/
├── SocketService.php # Haupt-Service (Facade)
├── SocketFactory.php # Socket-Erstellung
├── SocketServer.php # Server-Operationen
├── SocketClient.php # Client-Operationen
├── SocketConnection.php # Connection Wrapper
├── SocketConnectionPool.php # Connection Pool Management
├── SocketsInitializer.php # DI-Initializer
├── Exceptions/ # Exception-Klassen
├── ValueObjects/ # Type-safe Value Objects
└── Integration/ # PCNTL & Async Integration
```
## Value Objects
### SocketAddress
Repräsentiert eine Socket-Adresse (IPv4, IPv6 oder Unix Domain Socket).
```php
use App\Framework\Sockets\ValueObjects\SocketAddress;
// IPv4 Adresse
$address = SocketAddress::ipv4('127.0.0.1', 8080);
// IPv6 Adresse
$address = SocketAddress::ipv6('::1', 8080);
// Unix Domain Socket
$address = SocketAddress::unix('/tmp/socket.sock');
// Von String parsen
$address = SocketAddress::fromString('127.0.0.1:8080');
$address = SocketAddress::fromString('/tmp/socket.sock');
// Eigenschaften
$host = $address->getHost(); // null für Unix Sockets
$port = $address->getPort(); // null für Unix Sockets
$path = $address->getUnixPath(); // null für Network Sockets
$protocol = $address->getProtocol(); // SocketProtocol Enum
$isUnix = $address->isUnixSocket();
$isNetwork = $address->isNetworkSocket();
$string = $address->toString(); // "127.0.0.1:8080" oder "/tmp/socket.sock"
```
### SocketType
Enum für Socket-Typen.
```php
use App\Framework\Sockets\ValueObjects\SocketType;
SocketType::TCP // SOCK_STREAM
SocketType::UDP // SOCK_DGRAM
SocketType::RAW // SOCK_RAW
SocketType::RDM // SOCK_RDM
SocketType::SEQPACKET // SOCK_SEQPACKET
// Methoden
$type->getName(); // "TCP", "UDP", etc.
$type->getValue(); // SOCK_STREAM, SOCK_DGRAM, etc.
$type->isReliable(); // true für TCP, SEQPACKET
$type->isConnectionless(); // true für UDP
```
### SocketProtocol
Enum für Protokoll-Familien.
```php
use App\Framework\Sockets\ValueObjects\SocketProtocol;
SocketProtocol::IPv4 // AF_INET
SocketProtocol::IPv6 // AF_INET6
SocketProtocol::UNIX // AF_UNIX
// Methoden
$protocol->getName(); // "IPv4", "IPv6", "Unix Domain"
$protocol->getValue(); // AF_INET, AF_INET6, AF_UNIX
$protocol->isNetwork(); // true für IPv4/IPv6
$protocol->isUnix(); // true für Unix Domain
```
### SocketOption
Enum für Socket-Optionen.
```php
use App\Framework\Sockets\ValueObjects\SocketOption;
SocketOption::SO_REUSEADDR
SocketOption::SO_REUSEPORT
SocketOption::SO_KEEPALIVE
SocketOption::SO_LINGER
SocketOption::SO_RCVBUF
SocketOption::SO_SNDBUF
SocketOption::SO_RCVTIMEO
SocketOption::SO_SNDTIMEO
SocketOption::TCP_NODELAY
SocketOption::TCP_KEEPIDLE
SocketOption::TCP_KEEPINTVL
SocketOption::TCP_KEEPCNT
// Methoden
$option->getName(); // "SO_REUSEADDR", etc.
$option->getLevel(); // SOL_SOCKET oder SOL_TCP
$option->getValue(); // SO_REUSEADDR, etc.
```
### SocketResource
Type-safe Wrapper für Socket-Ressourcen mit automatischem Cleanup.
```php
use App\Framework\Sockets\ValueObjects\SocketResource;
$resource = SocketResource::fromResource($socket, $type, $protocol);
// Eigenschaften
$socketResource = $resource->getResource(); // Native Socket-Resource
$type = $resource->getType(); // SocketType
$protocol = $resource->getProtocol(); // SocketProtocol
$isClosed = $resource->isClosed();
// Manuelles Schließen (automatisch im Destructor)
$resource->close();
```
## Core Services
### SocketFactory
Factory für Socket-Erstellung mit automatischem Option-Setup.
```php
use App\Framework\Sockets\SocketFactory;
use App\Framework\Sockets\ValueObjects\SocketAddress;
use App\Framework\Sockets\ValueObjects\SocketType;
use App\Framework\Sockets\ValueObjects\SocketProtocol;
$factory = new SocketFactory();
// TCP Socket erstellen
$address = SocketAddress::ipv4('127.0.0.1', 8080);
$socket = $factory->createTcp($address);
// UDP Socket erstellen
$socket = $factory->createUdp($address);
// Unix Domain Socket erstellen
$unixAddress = SocketAddress::unix('/tmp/socket.sock');
$socket = $factory->createUnix($unixAddress);
// Generische Erstellung
$socket = $factory->createServer(SocketType::TCP, SocketProtocol::IPv4);
$socket = $factory->createClient(SocketType::TCP, SocketProtocol::IPv4);
```
### SocketServer
Server-Operationen für Socket-Verwaltung.
```php
use App\Framework\Sockets\SocketServer;
use App\Framework\Sockets\ValueObjects\SocketAddress;
use App\Framework\Sockets\ValueObjects\SocketResource;
$server = new SocketServer();
$address = SocketAddress::ipv4('0.0.0.0', 8080);
// Socket binden
$server->bind($socket, $address);
// Auf Verbindungen lauschen
$server->listen($socket, 10); // backlog = 10
// Verbindung akzeptieren (non-blocking)
$connection = $server->accept($socket);
if ($connection !== null) {
// Verbindung verarbeiten
$clientSocket = $connection->getSocket();
$clientAddress = $connection->getAddress();
}
// Socket-Auswahl (select)
$read = [$socket];
$write = [];
$except = [];
$numReady = $server->select($read, $write, $except, 1); // 1 Sekunde Timeout
// Non-blocking/Blocking Mode
$server->setNonBlocking($socket);
$server->setBlocking($socket);
```
### SocketClient
Client-Operationen für Socket-Verbindungen.
```php
use App\Framework\Sockets\SocketClient;
use App\Framework\Sockets\ValueObjects\SocketAddress;
use App\Framework\Sockets\ValueObjects\SocketResource;
$client = new SocketClient();
$address = SocketAddress::ipv4('127.0.0.1', 8080);
// Verbindung herstellen
$client->connect($socket, $address);
// Daten lesen
$data = $client->read($socket, 1024); // null wenn keine Daten (non-blocking)
// Daten schreiben
$bytesWritten = $client->write($socket, "Hello, World!");
// Daten senden (mit Flags)
$bytesSent = $client->send($socket, $data, MSG_DONTWAIT);
// Daten empfangen
$data = $client->receive($socket, 1024, MSG_DONTWAIT);
// Verbindung schließen
$client->close($socket);
```
### SocketConnection
Wrapper für Socket-Verbindungen mit Metadaten.
```php
use App\Framework\Sockets\SocketConnection;
$connection = SocketConnection::create($socketResource, $address);
// Eigenschaften
$socket = $connection->getSocket();
$address = $connection->getAddress();
$connectionId = $connection->getConnectionId();
$isClosed = $connection->isClosed();
// Verbindung schließen
$connection->close();
```
### SocketConnectionPool
Verwaltung mehrerer Socket-Verbindungen.
```php
use App\Framework\Sockets\SocketConnectionPool;
$pool = new SocketConnectionPool(
maxConnectionsPerAddress: 5,
connectionTimeoutSeconds: 300
);
// Verbindung hinzufügen
$pool->add($connection);
// Verbindung entfernen
$pool->remove($connection);
// Verbindung abrufen
$connection = $pool->get($connectionId);
$connections = $pool->getConnectionsByAddress($address);
$connection = $pool->getConnectionForAddress($address);
// Dead Connections bereinigen
$removed = $pool->cleanupDeadConnections();
// Statistiken
$count = $pool->getConnectionCount();
$allConnections = $pool->getAllConnections();
```
### SocketService
Haupt-Facade für alle Socket-Operationen.
```php
use App\Framework\Sockets\SocketService;
$socketService = $container->get(SocketService::class);
// Socket-Erstellung
$socket = $socketService->createTcp($address);
$socket = $socketService->createUdp($address);
$socket = $socketService->createUnix($address);
// Server-Operationen
$socketService->bind($socket, $address);
$socketService->listen($socket, 10);
$connection = $socketService->accept($socket);
$socketService->setNonBlocking($socket);
// Client-Operationen
$socketService->connect($socket, $address);
$data = $socketService->read($socket, 1024);
$bytes = $socketService->write($socket, $data);
// Connection Pool
$socketService->addConnection($connection);
$socketService->removeConnection($connection);
$connection = $socketService->getConnection($connectionId);
$removed = $socketService->cleanupDeadConnections();
```
## Integration
### PCNTL Integration
Socket-Server in geforkten Worker-Prozessen für Load Balancing.
```php
use App\Framework\Sockets\Integration\PcntlSocketServer;
use App\Framework\Sockets\SocketService;
use App\Framework\Pcntl\PcntlService;
use App\Framework\Sockets\ValueObjects\SocketAddress;
use App\Framework\Sockets\ValueObjects\SocketResource;
$socketService = $container->get(SocketService::class);
$pcntlService = $container->get(PcntlService::class);
$pcntlServer = new PcntlSocketServer(
socketService: $socketService,
pcntlService: $pcntlService,
maxWorkers: 4
);
// Connection Handler setzen
$pcntlServer->setConnectionHandler(function (SocketConnection $connection) {
// Verbindung verarbeiten
$socket = $connection->getSocket();
$data = $socketService->read($socket->getResource(), 1024);
// ...
});
// Server starten
$address = SocketAddress::ipv4('0.0.0.0', 8080);
$socket = $socketService->createTcp($address);
$pcntlServer->start($socket, $address, workerCount: 4);
// Server stoppen (graceful shutdown)
$pcntlServer->stop();
```
### Async Integration
Non-blocking Socket-Server mit Fibers für parallele Connection-Verarbeitung.
```php
use App\Framework\Sockets\Integration\AsyncSocketServer;
use App\Framework\Sockets\SocketService;
use App\Framework\Async\FiberManager;
use App\Framework\Sockets\ValueObjects\SocketAddress;
$socketService = $container->get(SocketService::class);
$fiberManager = $container->get(FiberManager::class);
$asyncServer = new AsyncSocketServer(
socketService: $socketService,
fiberManager: $fiberManager
);
// Server starten (gibt Fiber zurück)
$address = SocketAddress::ipv4('0.0.0.0', 8080);
$socket = $socketService->createTcp($address);
$serverFiber = $asyncServer->startAsync(
socket: $socket,
address: $address,
connectionHandler: function (SocketConnection $connection) {
// Connection in separatem Fiber verarbeiten
$socket = $connection->getSocket();
// Non-blocking lesen
$readFiber = $asyncServer->readAsync($connection, 1024);
$data = $readFiber->start();
// Non-blocking schreiben
$writeFiber = $asyncServer->writeAsync($connection, "Response");
$bytes = $writeFiber->start();
}
);
// Server-Fiber starten
$serverFiber->start();
```
## Beispiele
### Einfacher TCP Server
```php
use App\Framework\Sockets\SocketService;
use App\Framework\Sockets\ValueObjects\SocketAddress;
$socketService = $container->get(SocketService::class);
$address = SocketAddress::ipv4('0.0.0.0', 8080);
// Socket erstellen
$socket = $socketService->createTcp($address);
// Binden und lauschen
$socketService->bind($socket, $address);
$socketService->listen($socket, 10);
$socketService->setNonBlocking($socket);
// Hauptschleife
while (true) {
// Verbindung akzeptieren
$connection = $socketService->accept($socket);
if ($connection !== null) {
$clientSocket = $connection->getSocket();
// Daten lesen
$data = $socketService->read($clientSocket, 1024);
if ($data !== null) {
// Antwort senden
$socketService->write($clientSocket, "Echo: " . $data);
}
// Verbindung schließen
$connection->close();
}
usleep(10000); // 10ms
}
```
### TCP Client
```php
use App\Framework\Sockets\SocketService;
use App\Framework\Sockets\ValueObjects\SocketAddress;
$socketService = $container->get(SocketService::class);
$address = SocketAddress::ipv4('127.0.0.1', 8080);
// Client-Socket erstellen
$socket = $socketService->createClient(
SocketType::TCP,
SocketProtocol::IPv4
);
// Verbinden
$socketService->connect($socket, $address);
// Daten senden
$socketService->write($socket, "Hello, Server!");
// Antwort lesen
$response = $socketService->read($socket, 1024);
// Verbindung schließen
$socketService->close($socket);
```
### Unix Domain Socket Server
```php
use App\Framework\Sockets\SocketService;
use App\Framework\Sockets\ValueObjects\SocketAddress;
$socketService = $container->get(SocketService::class);
$address = SocketAddress::unix('/tmp/mysocket.sock');
// Socket erstellen
$socket = $socketService->createUnix($address);
// Binden und lauschen
$socketService->bind($socket, $address);
$socketService->listen($socket, 10);
// Verbindungen akzeptieren
while (true) {
$connection = $socketService->accept($socket);
if ($connection !== null) {
// Verarbeitung
$socket = $connection->getSocket();
$data = $socketService->read($socket, 1024);
// ...
}
}
```
## Migration von bestehendem Code
### Von `socket_create()` zu `SocketFactory`
**Vorher:**
```php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
```
**Nachher:**
```php
$address = SocketAddress::ipv4('127.0.0.1', 8080);
$socket = $socketService->createTcp($address);
```
### Von `socket_bind()`/`socket_listen()` zu `SocketServer`
**Vorher:**
```php
socket_bind($socket, '127.0.0.1', 8080);
socket_listen($socket, 10);
```
**Nachher:**
```php
$address = SocketAddress::ipv4('127.0.0.1', 8080);
$socketService->bind($socket, $address);
$socketService->listen($socket, 10);
```
### Von `socket_accept()` zu `SocketServer::accept()`
**Vorher:**
```php
$clientSocket = socket_accept($socket);
```
**Nachher:**
```php
$connection = $socketService->accept($socket);
if ($connection !== null) {
$clientSocket = $connection->getSocket();
}
```
### Von `socket_select()` zu `SocketServer::select()`
**Vorher:**
```php
socket_select($read, $write, $except, 1);
```
**Nachher:**
```php
$numReady = $socketService->select($read, $write, $except, 1);
```
### Von `socket_read()`/`socket_write()` zu `SocketClient`
**Vorher:**
```php
$data = socket_read($socket, 1024);
socket_write($socket, $data, strlen($data));
```
**Nachher:**
```php
$data = $socketService->read($socket, 1024);
$bytes = $socketService->write($socket, $data);
```
### Von `socket_close()` zu `SocketResource` Destructor
**Vorher:**
```php
socket_close($socket);
```
**Nachher:**
```php
// Automatisch im Destructor, oder manuell:
$socket->close();
```
## Fehlerbehandlung
Das Sockets-Modul verwendet spezifische Exceptions für verschiedene Fehlertypen:
```php
use App\Framework\Sockets\Exceptions\SocketException;
use App\Framework\Sockets\Exceptions\SocketBindException;
use App\Framework\Sockets\Exceptions\SocketConnectException;
use App\Framework\Sockets\Exceptions\SocketReadException;
try {
$socketService->bind($socket, $address);
} catch (SocketBindException $e) {
// Bind-Fehler behandeln
error_log("Failed to bind: " . $e->getMessage());
}
try {
$socketService->connect($socket, $address);
} catch (SocketConnectException $e) {
// Connect-Fehler behandeln
error_log("Failed to connect: " . $e->getMessage());
}
try {
$data = $socketService->read($socket, 1024);
} catch (SocketReadException $e) {
// Read-Fehler behandeln
if ($e->getMessage() === 'Socket connection closed') {
// Verbindung geschlossen
}
}
```
## Best Practices
1. **SocketService verwenden**: Nutze immer `SocketService` als Haupt-API statt direkter Aufrufe der einzelnen Services
2. **Value Objects**: Verwende immer Value Objects (`SocketAddress`, `SocketType`, etc.) statt primitiver Typen
3. **Resource Management**: `SocketResource` kümmert sich automatisch um Cleanup, aber manuelles Schließen ist für explizite Kontrolle möglich
4. **Non-blocking I/O**: Verwende `setNonBlocking()` für Server-Sockets, um mehrere Verbindungen parallel zu handhaben
5. **Connection Pooling**: Nutze `SocketConnectionPool` für Client-Verbindungen, die wiederverwendet werden sollen
6. **Error Handling**: Fange spezifische Exceptions (`SocketBindException`, `SocketConnectException`, etc.) für präzise Fehlerbehandlung
7. **PCNTL für Load Balancing**: Verwende `PcntlSocketServer` für Socket-Server, die mehrere Worker-Prozesse benötigen
8. **Async für Parallelität**: Verwende `AsyncSocketServer` für non-blocking I/O mit Fibers
## Dependency Injection
Alle Services werden automatisch über `SocketsInitializer` im DI-Container registriert:
```php
use App\Framework\Sockets\SocketService;
use App\Framework\Sockets\SocketFactory;
use App\Framework\Sockets\SocketServer;
use App\Framework\Sockets\SocketClient;
// Services sind im Container verfügbar
$socketService = $container->get(SocketService::class);
$factory = $container->get(SocketFactory::class);
$server = $container->get(SocketServer::class);
$client = $container->get(SocketClient::class);
```
## Framework-Kompatibilität
Das Sockets-Modul folgt allen Framework-Prinzipien:
-**Final readonly classes** wo möglich
-**Value Objects** statt Primitiven
-**Dependency Injection** überall
-**Composition** statt Inheritance
-**Strict Types** (`declare(strict_types=1)`)
-**PSR-12** Code Style
## Siehe auch
- [PCNTL Module Documentation](./pcntl-module.md) - Für PCNTL-Integration
- [Async Module Documentation](./async-module.md) - Für Async-Integration
- [Framework Guidelines](./guidelines.md) - Allgemeine Framework-Prinzipien

File diff suppressed because it is too large Load Diff

26
docs/codex/guidelines.md Normal file
View File

@@ -0,0 +1,26 @@
# Codex Agent Guidelines
This document supplements `AGENTS.md` with Codex-specific working notes. Always treat `AGENTS.md` as the source of truth and keep this file aligned with future updates.
## Core Expectations
- Obtain explicit approval from the project owner before attempting any code change or file edit.
- Follow every checklist item in `AGENTS.md`, including framework principles, testing strategy, and tooling conventions.
- Keep documentation edits consistent with project tone (PSR-12 code examples, ASCII character set, precise terminology).
## Workflow Notes
- Prefer small, reviewable steps and clearly report what changed, including file paths and line references.
- When a task involves multiple steps, draft a lightweight plan unless the work is trivial.
- Record unanswered questions or ambiguities in the final message so the owner can respond quickly.
## Tooling Reminders
- Use `bash -lc` shell invocations with explicit `workdir` as required by the Codex CLI harness.
- Rely on `rg` for searches; fall back to alternatives only if `rg` is unavailable.
- Do not run container or network commands without explicit permission when sandboxed.
## Documentation Maintenance
- Update this file whenever Codex-specific guidance changes so it remains synchronized with the rest of the ecosystem docs (e.g., keep parity with `docs/claude/` where it makes sense).
- Coordinate with the project owner before introducing new sections or workflows that impact other agents.

View File

@@ -204,13 +204,13 @@ Roave automatically blocks `composer install` or `composer update` if any instal
Current project uses **PHP 8.5 RC3** (bleeding edge), which causes dependency resolution conflicts:
```
brianium/paratest v7.8.4 requires php ~8.2.0 || ~8.3.0 || ~8.4.0
your php version (8.5.0RC3) does not satisfy that requirement
your php version (8.5.0RC4) does not satisfy that requirement
```
**Planned Integration:** When PHP 8.5 stable is released and all testing dependencies support it.
> **PHP Runtime Strategy:**
> - Runtime container builds accept `--build-arg PHP_VERSION` (default `8.5.0RC3`) to keep PHP aligned with upstream RC tags.
> - Runtime container builds accept `--build-arg PHP_VERSION` (default `8.5.0RC4`) to keep PHP aligned with upstream RC tags.
> - `.gitea/workflows/production-deploy.yml` sets the same version for CI rebuilds (`--pull` ensures fresh layers).
> - We'll move to `8.5.0RC4` as soon as upstream publishes the image and switch to the latest stable PHP release at the end of November.

View File

@@ -0,0 +1,22 @@
# Deployment Fix f?r Staging 502 Error
Das Problem: Nach jedem Deployment tritt der 502-Fehler wieder auf.
## L?sung: Deployment-Script erweitern
F?ge nach Zeile 991 in `.gitea/workflows/build-image.yml` folgenden Code ein:
```yaml
# Fix nginx upstream configuration - critical fix for 502 errors
# sites-available/default uses 127.0.0.1:9000 but PHP-FPM runs in staging-app container
echo \"?? Fixing nginx PHP-FPM upstream configuration (post-deploy fix)...\"
sleep 5
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server 127.0.0.1:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || echo \"?? Upstream fix (127.0.0.1) failed\"
docker compose exec -T staging-nginx sed -i '/upstream php-upstream {/,/}/s|server localhost:9000;|server staging-app:9000;|g' /etc/nginx/sites-available/default || echo \"?? Upstream fix (localhost) failed\"
docker compose exec -T staging-nginx nginx -t && docker compose restart staging-nginx || echo \"?? Nginx config test or restart failed\"
echo \"? Nginx configuration fixed and reloaded\"
```
**Position:** Nach Zeile 991 (`docker compose restart staging-app || echo \"?? Failed to restart staging-app\"`) und vor Zeile 993 (`echo \"? Waiting for services to stabilize...\"`)
**Grund:** Die Container werden mit `--force-recreate` neu erstellt, wodurch die Datei `/etc/nginx/sites-available/default` wieder aus dem Docker-Image kommt und `127.0.0.1:9000` verwendet. Dieser Fix muss nach jedem Deployment ausgef?hrt werden.

View File

@@ -0,0 +1,266 @@
# Environment Configuration Guide
## 📁 .env File Structure (Base + Override Pattern)
Die neue Struktur verwendet ein **Base + Override Pattern** (analog zu docker-compose):
```
├── .env.example # Template für neue Entwickler (vollständige Dokumentation)
├── .env.base # Gemeinsame Variablen für alle Environments (versioniert)
├── .env.local # Lokale Development-Overrides (gitignored)
├── .env.staging # Staging-spezifische Overrides (optional, gitignored)
└── .env.production # Production (generiert durch Ansible, nicht im Repo)
```
## 🏗️ Development Setup
### Initial Setup
```bash
# 1. .env.base ist bereits im Repository (gemeinsame Variablen)
# 2. Erstelle .env.local für lokale Overrides
cp .env.example .env.local
# 3. Passe .env.local an deine lokale Entwicklung an
# - DB Credentials (lokal)
# - API Keys (lokal)
# - Debug-Flags
```
### Framework lädt automatisch: `.env.base` → `.env.local` (Overrides)
**Priorität:**
1. System Environment Variables (Docker ENV)
2. `.env.base` (gemeinsame Basis)
3. `.env.local` (lokale Overrides)
4. `.env.secrets` (verschlüsselte Secrets, optional)
**Wichtig:** `env_file` in Docker Compose ist nicht nötig!
- Framework lädt automatisch `.env.base``.env.local` via `EncryptedEnvLoader`
- Docker Compose `env_file` ist optional und wird nur für Container-interne Variablen benötigt
- PHP-Anwendung lädt ENV-Variablen direkt aus den Dateien
**Backward Compatibility:**
- Falls `.env.base` oder `.env.local` nicht existieren, wird `.env` geladen (Fallback)
- Migration: Bestehende `.env` Files funktionieren weiterhin
## 🚀 Production Deployment
### Production .env Management
**WICHTIG**: Production `.env` wird **NICHT** aus dem Repository deployed!
### Single Source of Truth
```
Server: /home/deploy/michaelschiemer/shared/.env.production
```
Dieser File wird von **Ansible** automatisch erstellt aus:
```
deployment/infrastructure/templates/.env.production.j2
```
### Production Deployment Process
```bash
# Ansible Playbook erstellt automatisch die Production .env
cd deployment/infrastructure
ansible-playbook -i inventories/production/hosts.yml \
playbooks/deploy-rsync-based.yml \
--vault-password-file .vault_pass
```
**Ansible macht dabei**:
1. Template `.env.production.j2` rendern
2. Vault-verschlüsselte Secrets einsetzen
3. File nach `/home/deploy/michaelschiemer/shared/.env.production` deployen
4. Docker Compose mounted diesen File in Container
## 🔒 Security & Secret Management
### Docker Secrets (Production & Staging)
**Production und Staging verwenden Docker Secrets:**
1. **Ansible Vault → Docker Secrets Dateien**
- Ansible Playbook erstellt Secret-Dateien in `secrets/` Verzeichnis
- Dateien haben sichere Permissions (0600)
2. **Docker Compose Secrets**
- Secrets werden in `docker-compose.base.yml` definiert
- Environment-Variablen nutzen `*_FILE` Pattern (z.B. `DB_PASSWORD_FILE=/run/secrets/db_user_password`)
- Framework lädt automatisch via `DockerSecretsResolver`
3. **Framework Support**
- `DockerSecretsResolver` unterstützt automatisch `*_FILE` Pattern
- Kein manuelles Secret-Loading mehr nötig (wird automatisch vom Framework behandelt)
### Development
```bash
# .env.local niemals committen
git status
# Should show: .env.local (untracked) ✅
# .env.base ist versioniert (keine Secrets!)
# Falls versehentlich staged:
git reset HEAD .env.local
```
### Production
- ✅ Secrets in Ansible Vault
- ✅ Ansible erstellt Docker Secrets Dateien (`secrets/*.txt`)
- ✅ Docker Compose Secrets aktiviert
- ✅ Framework lädt automatisch via `*_FILE` Pattern
- ✅ .env.production auf Server wird NICHT ins Repository committed
- ✅ Template `application.env.j2` verwendet `*_FILE` Pattern
## 📝 Adding New Environment Variables
### Development
```bash
# 1. Add to .env.base if shared across environments
echo "NEW_API_KEY=" >> .env.base
# 2. Add to .env.local for local development
echo "NEW_API_KEY=abc123..." >> .env.local
# 3. Update .env.example for documentation
echo "NEW_API_KEY=your_api_key_here" >> .env.example
```
**Hinweis:** Wenn die Variable nur für lokale Entwicklung ist, nur in `.env.local` hinzufügen.
### Production (mit Docker Secrets)
```bash
# 1. Add to Ansible Template (use *_FILE pattern for secrets)
# File: deployment/ansible/templates/application.env.j2
echo "# Use Docker Secrets via *_FILE pattern" >> application.env.j2
echo "NEW_API_KEY_FILE=/run/secrets/new_api_key" >> application.env.j2
# 2. Add to docker-compose.base.yml secrets section
# File: docker-compose.base.yml
# secrets:
# new_api_key:
# file: ./secrets/new_api_key.txt
# 3. Add secret to Ansible Vault
ansible-vault edit deployment/ansible/secrets/production.vault.yml
# Add: vault_new_api_key: "production_value"
# 4. Update setup-production-secrets.yml to create secret file
# File: deployment/ansible/playbooks/setup-production-secrets.yml
# Add to loop:
# - name: new_api_key
# value: "{{ vault_new_api_key }}"
# 5. Deploy
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/setup-production-secrets.yml \
--vault-password-file .vault_pass
```
### Production (ohne Docker Secrets, fallback)
Falls Docker Secrets nicht verwendet werden sollen:
```bash
# 1. Add to Ansible Template
# File: deployment/ansible/templates/application.env.j2
echo "NEW_API_KEY={{ vault_new_api_key }}" >> application.env.j2
# 2. Add secret to Ansible Vault
ansible-vault edit deployment/ansible/secrets/production.vault.yml
# Add: vault_new_api_key: "production_value"
# 3. Deploy
cd deployment/ansible
ansible-playbook -i inventory/production.yml \
playbooks/deploy-update.yml
```
## 🗑️ Removed Files (Consolidation 27.10.2024)
Diese Files wurden gelöscht, da sie redundant/nicht verwendet wurden:
```
❌ .env.production (Root - redundant)
❌ .env.production.example (Root - nicht verwendet)
❌ .env.backup.20250912_133135 (Altes Backup)
❌ .env.analytics.example (In .env.example integriert)
❌ .env.secrets.example (In .env.example integriert)
❌ deployment/applications/environments/ (Gesamtes Directory gelöscht)
```
## ✅ Current State
### Local Development
- ✅ Base File: `.env.base` (versioniert, gemeinsame Variablen)
- ✅ Override File: `.env.local` (gitignored, lokale Anpassungen)
- ✅ Template: `.env.example` (Dokumentation)
- ✅ Framework lädt automatisch: `.env.base``.env.local` (Overrides)
### Production
- ✅ Single Source: `/home/deploy/michaelschiemer/shared/.env.production` (auf Server)
- ✅ Verwaltet durch: Ansible Template `application.env.j2`
- ✅ Secrets: Docker Secrets (`secrets/*.txt` Dateien)
- ✅ Framework lädt automatisch via `*_FILE` Pattern (`DockerSecretsResolver`)
- ✅ Keine Duplikate
### Staging
- ✅ Docker Compose Environment Variables
- ✅ Docker Secrets aktiviert (wie Production)
- ✅ Optional: `.env.staging` für Staging-spezifische Overrides
## 🔍 Verification
```bash
# Check local .env files
ls -la .env*
# Should show: .env.base (versioniert), .env.local (gitignored), .env.example
# Check Ansible template exists
ls -la deployment/ansible/templates/application.env.j2
# Should exist
# Check Docker Secrets files exist (on server)
ls -la {{ app_stack_path }}/secrets/
# Should show: db_user_password.txt, redis_password.txt, app_key.txt, etc.
# Check NO old files remain
find . -name ".env.production" -o -name ".env.*.example" | grep -v .env.example | grep -v .env.base
# Should be empty
```
## 📞 Support
Bei Fragen zum .env Setup:
- Development: Siehe `.env.base` (gemeinsame Variablen) und `.env.example` (Dokumentation)
- Production: Siehe `deployment/ansible/templates/application.env.j2`
- Secrets: Docker Secrets aktiviert, verwaltet durch Ansible Vault
- Migration: Framework unterstützt Fallback auf `.env` (alte Struktur)
## 🔄 Migration von alter Struktur
**Von `.env` zu `.env.base` + `.env.local`:**
```bash
# 1. Erstelle .env.base (gemeinsame Variablen extrahieren)
# (wird automatisch vom Framework erkannt)
# 2. Erstelle .env.local (nur lokale Overrides)
cp .env .env.local
# 3. Entferne gemeinsame Variablen aus .env.local
# (nur lokale Anpassungen behalten)
# 4. Alte .env kann später entfernt werden
# (nach erfolgreicher Migration)
```
**Hinweis:** Framework lädt automatisch `.env.base` + `.env.local`. Falls diese nicht existieren, wird `.env` als Fallback geladen (Backward Compatibility).

View File

@@ -0,0 +1,100 @@
# Deployment-Test Status - Chat-Zusammenfassung
**Datum**: Aktuelle Session
**Zweck**: Staging-Setup mit separaten Datenbank-Stacks testen
## ✅ Abgeschlossen
### 1. Implementierung
- ✅ Separate PostgreSQL-Stacks erstellt (Production & Staging)
- ✅ Ansible-Roles für PostgreSQL-Stacks
- ✅ Application-Stacks angepasst (DB-Verbindungen)
- ✅ Staging-Setup Playbook erstellt
- ✅ Dokumentation aktualisiert
- ✅ Quick-Start-Scripts erstellt
- ✅ Ansible-Verifikations-Playbooks erstellt
### 2. Lokale Verifikation
- ✅ PostgreSQL-Production Stack: Syntax OK
- ✅ PostgreSQL-Staging Stack: Syntax OK
- ✅ Staging Stack (Root): Syntax OK
- ⚠️ Ansible: Nicht lokal installiert (wird auf Control-Node benötigt)
## ❌ Aktuelle Probleme
### SSH-Zugriff
- **Problem**: SSH-Key kann nicht geladen werden
- **Fehler**: `error in libcrypto` / `Permission denied (publickey)`
- **Key vorhanden**: `~/.ssh/production` (Berechtigungen: 600)
- **Mögliche Ursachen**: Key-Format, WSL/libcrypto-Kompatibilität
## 📋 Nächste Schritte
### Option 1: Manuelle Tests auf Server
- **Anleitung**: `deployment/docs/guides/manual-server-test.md`
- **Schritte**:
1. SSH-Verbindung: `ssh production`
2. PostgreSQL-Stacks starten
3. Networks verifizieren
4. Datenbank-Verbindungen testen
5. Health-Checks durchführen
### Option 2: Ansible verwenden
```bash
cd ~/dev/michaelschiemer/deployment/ansible
ansible-playbook -i inventory/production.yml playbooks/verify-staging.yml
```
### Option 3: Quick-Start-Script (auf Server)
```bash
cd ~/deployment
./scripts/staging-quick-start.sh
```
## 📁 Wichtige Dateien
### Dokumentation
- `deployment/docs/guides/test-execution-plan.md` - Detaillierter Testplan
- `deployment/docs/guides/manual-server-test.md` - Manuelle Test-Anleitung
- `deployment/docs/guides/ansible-vs-bash-scripts.md` - Tool-Vergleich
### Scripts
- `deployment/scripts/staging-quick-start.sh` - Interaktives Test-Script
- `deployment/scripts/production-quick-start.sh` - Production Test-Script
### Ansible-Playbooks
- `deployment/ansible/playbooks/setup-staging.yml` - Staging-Setup
- `deployment/ansible/playbooks/verify-staging.yml` - Staging-Verifikation
- `deployment/ansible/playbooks/verify-production.yml` - Production-Verifikation
## 🎯 Test-Phasen (noch ausstehend)
1. ✅ Phase 1: Lokale Syntax-Verifikation
2. ⏳ Phase 2: PostgreSQL-Stacks testen (auf Server)
3. ⏳ Phase 3: Networks verifizieren
4. ⏳ Phase 4: Ansible-Setup testen
5. ⏳ Phase 5: Datenbank-Verbindungen testen
6. ⏳ Phase 6: Health-Checks
7. ⏳ Phase 7: CI/CD-Workflow testen
8. ⏳ Phase 8: Datenbank-Isolation testen
## 💡 Empfehlung für Fortsetzung
1. **Server-Neuaufbau durchführen** (siehe `deployment/docs/guides/server-rebuild-plan.md`)
- ✅ Detaillierter Plan erstellt (Debian 13 Trixie + UEFI)
- ✅ SSH-Zugriff dokumentiert (`deployment/docs/guides/ssh-access.md`)
- ✅ Initial-Server-Setup Playbook erstellt (`deployment/ansible/playbooks/initial-server-setup.yml`)
- ✅ Docker-Installation für Debian angepasst
- ⏳ Server über Netcup Control Panel zurücksetzen (Debian 13 Trixie UEFI)
- ⏳ Komplettes Setup via Ansible
2. **Nach Neuaufbau**: PostgreSQL-Stacks, Ansible-Verifikation, End-to-End-Tests
## 🔧 Bekannte Issues
- SSH-Key-Problem: `error in libcrypto` - muss behoben werden für automatische Tests
- Alternative: Manuelle Tests oder Ansible verwenden
---
**Hinweis**: Dieser Status kann mit `cursor-agent resume` fortgesetzt werden.

374
docs/design-token-system.md Normal file
View File

@@ -0,0 +1,374 @@
# Design Token System Dokumentation
## Übersicht
Das Design Token System ermöglicht die zentrale Verwaltung von Design-Tokens (Farben, Abstände, Typografie, etc.) in PHP mit automatischer CSS-Generierung. Es unterstützt moderne CSS-Features wie OKLCH-Farben, HDR/P3-Support, Dark Mode und State-basierte Token-Variationen.
## Architektur
### Kernkomponenten
1. **TokenRegistry** - Basis-Klasse für Token-Registries
2. **ColorVariation** - Verwaltet Farben mit Light/Dark/P3/Fallback-Varianten
3. **ColorManipulator** - Service für Farbmanipulation
4. **StateMutation** - Definiert Mutationen für Token-States
5. **TokenStateRegistry** - Verwaltet Tokens mit States
6. **CssAstBuilder** - Generiert CSS aus Tokens
### Token-Typen
- **ColorToken** - Farb-Token mit Variationen
- **StatefulColorToken** - Farb-Token mit States (hover, disabled, etc.)
- **SpacingToken** - Abstands-Token
- **TypographyToken** - Typografie-Token
## Farbmanipulation
### ColorManipulator Service
Der `ColorManipulator` Service bietet Methoden zur Manipulation von Farben:
```php
use App\Framework\Design\Services\ColorManipulator;
use App\Framework\Design\ValueObjects\CssColor;
use App\Framework\Design\ValueObjects\ColorFormat;
$manipulator = new ColorManipulator();
$primary = new CssColor('oklch(70% 0.2 295)', ColorFormat::OKLCH);
// Helligkeit anpassen
$lighter = $manipulator->lighten($primary, 0.1); // 10% heller
$darker = $manipulator->darken($primary, 0.2); // 20% dunkler
// Sättigung anpassen
$moreSaturated = $manipulator->saturate($primary, 0.15);
$lessSaturated = $manipulator->desaturate($primary, 0.5);
// Transparenz ändern
$semiTransparent = $manipulator->adjustOpacity($primary, 0.5);
// Farben mixen
$secondary = new CssColor('oklch(60% 0.2 145)', ColorFormat::OKLCH);
$mixed = $manipulator->mix($primary, $secondary, 0.3); // 30% primary, 70% secondary
// Farbton verschieben
$shifted = $manipulator->adjustHue($primary, 30); // 30 Grad verschieben
```
### CssColor Methoden
Farben können auch direkt manipuliert werden:
```php
$primary = new CssColor('oklch(70% 0.2 295)', ColorFormat::OKLCH);
$hover = $primary->lighten(0.1);
$active = $primary->darken(0.15);
$disabled = $primary->desaturate(1.0)->withOpacity(0.5);
$mixed = $primary->mix($secondary, 0.3);
```
## Token States
### TokenState Enum
Das `TokenState` Enum definiert verschiedene States für Tokens:
- `DEFAULT` - Standard State
- `DISABLED` - Deaktiviert
- `HOVER` - Hover State
- `ACTIVE` - Aktiv (z.B. gedrückt)
- `SELECTED` - Ausgewählt
- `FOCUSED` - Fokussiert
- `LOADING` - Lade-Zustand
- `ERROR` - Fehler-Zustand
- `SUCCESS` - Erfolgs-Zustand
- `WARNING` - Warnung-Zustand
### StateMutation
`StateMutation` definiert, wie ein Token für einen bestimmten State mutiert werden soll:
```php
use App\Framework\Design\ValueObjects\StateMutation;
use App\Framework\Design\ValueObjects\TokenState;
// Disabled State: 0% Sättigung, 50% Transparenz
$disabledMutation = new StateMutation(
saturationAdjustment: -1.0, // 0% Sättigung
opacityAdjustment: 0.5 // 50% Transparenz
);
// Hover State: 10% heller
$hoverMutation = new StateMutation(
lightnessAdjustment: 0.1
);
// Komposition mehrerer Mutationen
$desaturateMutation = new StateMutation(saturationAdjustment: -1.0);
$opacityMutation = new StateMutation(opacityAdjustment: 0.5);
$composedMutation = $desaturateMutation->compose($opacityMutation);
```
### StatefulColorToken
Ein `StatefulColorToken` repräsentiert einen Farb-Token mit einem spezifischen State:
```php
use App\Framework\Design\ValueObjects\Tokens\StatefulColorToken;
use App\Framework\Design\ValueObjects\ColorVariation;
use App\Framework\Design\ValueObjects\TokenState;
use App\Framework\Design\ValueObjects\StateMutation;
$primaryVariation = new ColorVariation(
name: 'primary',
light: new CssColor('oklch(70% 0.2 295)', ColorFormat::OKLCH),
dark: new CssColor('oklch(60% 0.22 295)', ColorFormat::OKLCH)
);
// Default State
$defaultToken = new StatefulColorToken(
name: 'button-primary',
variation: $primaryVariation,
state: TokenState::DEFAULT
);
// Disabled State (abgeleitet)
$disabledToken = new StatefulColorToken(
name: 'button-primary',
variation: $primaryVariation,
state: TokenState::DISABLED,
baseState: TokenState::DEFAULT,
mutation: new StateMutation(
saturationAdjustment: -1.0,
opacityAdjustment: 0.5
)
);
```
### TokenStateRegistry
Der `TokenStateRegistry` verwaltet Tokens mit States:
```php
use App\Framework\Design\ValueObjects\TokenStateRegistry;
use App\Framework\Design\ValueObjects\TokenState;
use App\Framework\Design\ValueObjects\StateMutation;
// Default Mutationen für States definieren
$registry = new TokenStateRegistry(
tokens: [],
stateMutations: [
TokenState::DISABLED => new StateMutation(
saturationAdjustment: -1.0,
opacityAdjustment: 0.5
),
TokenState::HOVER => new StateMutation(
lightnessAdjustment: 0.1
),
TokenState::ACTIVE => new StateMutation(
lightnessAdjustment: -0.15
),
]
);
// Token hinzufügen
$registry = $registry->addToken($defaultToken);
// Token für State abrufen
$hoverToken = $registry->getTokenForState('button-primary', TokenState::HOVER);
// Alle States für Token abrufen
$allStates = $registry->getAllStatesForToken('button-primary');
```
## CSS-Generierung
### Automatische CSS-Generierung
Das System generiert automatisch CSS aus Tokens:
```php
use App\Framework\Design\ValueObjects\FrameworkTokenRegistry;
$registry = new FrameworkTokenRegistry();
$css = $registry->toCss('framework-settings', includeHdr: true);
```
### CSS Output
Das generierte CSS nutzt moderne Features:
```css
@layer framework-settings {
:root {
--color-primary: oklch(70% 0.2 295);
--color-primary-p3: color(display-p3 0.8 0.3 1);
}
}
@layer framework-settings {
@media (prefers-color-scheme: dark) {
:root {
--color-primary: oklch(60% 0.22 295);
}
}
}
@layer framework-settings {
@media (dynamic-range: high) {
:root {
--color-primary: var(--color-primary-p3);
}
}
}
```
### State-basierte CSS mit Pseudo-Klassen
Für StatefulTokens werden Pseudo-Klassen generiert:
```css
.button-primary {
background: oklch(70% 0.2 295);
}
.button-primary:hover {
background: oklch(77% 0.2 295); /* Automatisch generiert */
}
.button-primary:active {
background: oklch(59.5% 0.2 295); /* Automatisch generiert */
}
.button-primary:disabled {
background: oklch(70% 0 295 / 0.5); /* Komponierte Mutation */
}
```
## Verwendung
### FrameworkTokenRegistry
Framework-weite Tokens:
```php
use App\Framework\Design\ValueObjects\FrameworkTokenRegistry;
$registry = new FrameworkTokenRegistry();
$primaryColor = $registry->get('color-primary');
```
### AdminTokenRegistry
Admin-spezifische Tokens:
```php
use App\Application\Admin\ValueObjects\AdminTokenRegistry;
$registry = new AdminTokenRegistry();
$adminBg = $registry->get('admin-bg-primary');
```
### Token generieren
```bash
# Framework Tokens generieren
php console.php design:generate-tokens --scope=framework
# Admin Tokens generieren
php console.php design:generate-tokens --scope=admin
# Beide generieren
npm run build # Generiert automatisch beide vor dem Build
```
## Best Practices
### Farben definieren
1. **OKLCH verwenden**: Perzeptuell uniforme Farbmanipulation
2. **ColorVariation nutzen**: Zentrale Verwaltung von Light/Dark/P3
3. **HDR-Support**: Automatische P3-Varianten für HDR-Displays
### States definieren
1. **Basis-State**: Immer einen DEFAULT State definieren
2. **Mutationen komponieren**: Mehrere Mutationen kombinieren
3. **Konsistente Mutationen**: Gleiche Mutationen für ähnliche States
### Token-Organisation
1. **Scopes trennen**: Framework vs. Admin Tokens
2. **Naming Convention**: Klare, konsistente Namen
3. **Beschreibungen**: Immer Beschreibungen hinzufügen
## Erweiterte Features
### Custom State Mutationen
```php
// Komplexe Mutation: Desaturate + Opacity + Mix
$complexMutation = new StateMutation(
saturationAdjustment: -0.5,
opacityAdjustment: 0.7,
mixColor: new CssColor('oklch(50% 0 0)', ColorFormat::OKLCH), // Grau
mixWeight: 0.3
);
```
### State-Hierarchien
```php
// Disabled kann von Hover abgeleitet werden
$disabledFromHover = new StatefulColorToken(
name: 'button-primary',
variation: $primaryVariation,
state: TokenState::DISABLED,
baseState: TokenState::HOVER, // Basis ist Hover, nicht Default
mutation: new StateMutation(
saturationAdjustment: -1.0,
opacityAdjustment: 0.5
)
);
```
## Performance
- **Caching**: Generierte CSS wird gecacht
- **Lazy Loading**: Tokens werden nur bei Bedarf geladen
- **Optimierte Konvertierung**: OKLCH-Konvertierung ist optimiert
## Browser-Unterstützung
- **OKLCH**: Moderne Browser (Chrome 111+, Safari 15.4+, Firefox 113+)
- **Display P3**: HDR-Displays mit Wide-Gamut-Support
- **Fallbacks**: Automatische RGB/HEX-Fallbacks für ältere Browser
## Migration von bestehenden Tokens
Bestehende Tokens können schrittweise migriert werden:
1. **ColorVariation erstellen**: Light/Dark Varianten definieren
2. **States hinzufügen**: Mutationen für States definieren
3. **CSS aktualisieren**: Generierte CSS verwenden
## Troubleshooting
### Farben sehen falsch aus
- Prüfe OKLCH-Werte (Lightness 0-1 oder 0-100%, Chroma 0-0.4+, Hue 0-360)
- Verwende ColorManipulator für konsistente Manipulation
### States funktionieren nicht
- Prüfe ob Token StatefulTokenInterface implementiert
- Prüfe ob Mutation korrekt definiert ist
- Prüfe CSS-Output auf Pseudo-Klassen
### CSS wird nicht generiert
- Prüfe ob TokenRegistry korrekt initialisiert ist
- Prüfe ob Output-Pfad existiert und beschreibbar ist
- Prüfe Console-Output für Fehlermeldungen

View File

@@ -0,0 +1,754 @@
# Exception System Advanced Features
## Übersicht
Das Exception-System wurde um 10 erweiterte Features erweitert, die in drei Phasen implementiert wurden:
- **Phase 1 (Foundation)**: Rate Limiting, Context Caching, Performance Tracking
- **Phase 2 (User Experience)**: User-Friendly Messages, Localization
- **Phase 3 (Advanced)**: Recovery/Retry, Pattern Detection, Correlation, Metrics, Health Checks
Alle Features sind optional und können einzeln aktiviert werden. Sie folgen den Framework-Prinzipien (final, readonly, Value Objects, Composition over Inheritance).
---
## Phase 1: Foundation Features
### 1. Exception Rate Limiting & Throttling
**Ziel**: Verhindert Log-Spam durch wiederholte gleiche Exceptions
**Komponenten**:
- `ExceptionFingerprint` - Generiert eindeutige Fingerprints für Exception-Gruppierung
- `ExceptionRateLimitConfig` - Konfiguration für Thresholds und Time Windows
- `ExceptionRateLimiter` - Rate Limiter mit Cache-basiertem Tracking
**Verwendung**:
```php
use App\Framework\ExceptionHandling\RateLimit\ExceptionRateLimiter;
use App\Framework\ExceptionHandling\RateLimit\ExceptionRateLimitConfig;
use App\Framework\Core\ValueObjects\Duration;
// Konfiguration erstellen
$config = ExceptionRateLimitConfig::withLimits(
maxExceptions: 10,
timeWindow: Duration::fromSeconds(60)
);
// Rate Limiter erstellen
$rateLimiter = new ExceptionRateLimiter($cache, $config);
// In ErrorKernel integriert (automatisch)
// Exceptions werden automatisch rate-limited, wenn Threshold erreicht wird
```
**Konfiguration**:
- `maxExceptions`: Maximale Anzahl gleicher Exceptions pro Time Window (Default: 10)
- `timeWindow`: Time Window für Rate Limiting (Default: 60 Sekunden)
- `skipLoggingOnLimit`: Skip Logging wenn Rate Limit erreicht (Default: true)
- `skipAuditOnLimit`: Skip Audit Logging wenn Rate Limit erreicht (Default: true)
- `trackMetricsOnLimit`: Track Metriken auch bei Rate Limit (Default: true)
**Fingerprint-Generierung**:
- Basierend auf Exception-Klasse, normalisierter Message, File/Line
- Optional: Component und Operation aus Context für präzisere Gruppierung
- Normalisierung entfernt variable Teile (UUIDs, Timestamps, Zahlen, etc.)
---
### 2. Exception Context Caching
**Ziel**: Performance-Optimierung durch Caching von häufig verwendeten Context-Daten
**Komponenten**:
- `ExceptionContextCache` - Cache-Wrapper für Context-Daten
- Integration in `ExceptionContextBuilder` - Automatischer Cache-Lookup
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Context\ExceptionContextCache;
use App\Framework\ExceptionHandling\Context\ExceptionContextBuilder;
// Context Cache erstellen
$contextCache = new ExceptionContextCache($cache);
// Context Builder mit Cache
$builder = new ExceptionContextBuilder(
errorScope: $errorScope,
contextCache: $contextCache
);
// Automatischer Cache-Lookup beim buildFromRequest()
$context = $builder->buildFromRequest($request);
```
**Cache-Levels**:
- **Request-Level**: TTL 10 Minuten (spezifischste)
- **Session-Level**: TTL 10 Minuten
- **User-Level**: TTL 30 Minuten (am wenigsten spezifisch)
**Cache-Invalidation**:
```php
// Manuelle Invalidation bei Context-Änderungen
$contextCache->invalidateRequest($requestId);
$contextCache->invalidateSession($sessionId);
$contextCache->invalidateUser($userId);
```
---
### 3. Exception Performance Tracking
**Ziel**: Tracking von Performance-Impact pro Exception-Typ
**Komponenten**:
- `ExceptionPerformanceMetrics` - Value Object für Metriken
- `ExceptionPerformanceTracker` - Performance-Tracking
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Performance\ExceptionPerformanceTracker;
$tracker = new ExceptionPerformanceTracker();
// Start tracking
$startData = $tracker->start();
// ... exception occurs ...
// End tracking
$metrics = $tracker->end($startData, $exception, $context);
// Metriken enthalten:
// - executionTimeMs: Ausführungszeit in Millisekunden
// - memoryDeltaBytes: Memory-Delta in Bytes
// - cpuUsagePercent: CPU-Usage in Prozent (wenn verfügbar)
```
**Integration**:
- Metriken werden automatisch in `ExceptionContextData::metadata['performance']` gespeichert
- Kann mit `MetricsCollector` integriert werden für Monitoring
---
## Phase 2: User Experience Features
### 4. User-Friendly Exception Messages
**Ziel**: Übersetzung von technischen Exception-Messages zu benutzerfreundlichen Texten
**Komponenten**:
- `UserFriendlyMessage` - Value Object für User-Messages
- `ExceptionMessageTranslator` - Message-Übersetzung mit Template-System
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Translation\ExceptionMessageTranslator;
use App\Framework\ExceptionHandling\Translation\UserFriendlyMessage;
// Templates definieren
$templates = [
\App\Framework\Exception\DatabaseException::class => [
'message' => 'Database connection failed. Please try again later.',
'title' => 'Database Error',
'help' => 'If this problem persists, please contact support.'
],
\App\Framework\Exception\ValidationException::class => [
'message' => 'Please check your input and try again.',
'title' => 'Validation Error'
]
];
// Translator erstellen
$translator = new ExceptionMessageTranslator(
templates: $templates,
isDebugMode: false
);
// Message übersetzen
$userMessage = $translator->translate($exception, $context);
// $userMessage->message: User-friendly message
// $userMessage->title: Optional title
// $userMessage->helpText: Optional help text
// $userMessage->technicalMessage: Original technical message (für Debugging)
```
**Template-Variablen**:
- `{exception_message}` - Original Exception-Message
- `{exception_class}` - Exception-Klasse
- `{operation}` - Operation aus Context
- `{component}` - Component aus Context
**Integration**:
- Automatisch in `ResponseErrorRenderer` integriert
- In Debug-Mode werden technische Messages angezeigt
- In Production werden User-Friendly Messages verwendet
---
### 5. Exception Localization
**Ziel**: i18n-Support für Exception-Messages basierend auf User-Locale
**Komponenten**:
- `ExceptionLocalizer` - Lokalisierung mit Fallback-Chain
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Localization\ExceptionLocalizer;
// Übersetzungen definieren
$translations = [
'de' => [
\App\Framework\Exception\DatabaseException::class => [
'message' => 'Datenbankverbindung fehlgeschlagen. Bitte versuchen Sie es später erneut.',
'title' => 'Datenbankfehler'
]
],
'en' => [
\App\Framework\Exception\DatabaseException::class => [
'message' => 'Database connection failed. Please try again later.',
'title' => 'Database Error'
]
]
];
// Localizer erstellen
$localizer = new ExceptionLocalizer(
translations: $translations,
defaultLocale: 'en'
);
// Locale aus Context extrahieren
$locale = $localizer->getLocale($context);
// Übersetzungen für Locale abrufen
$localeTranslations = $localizer->getTranslations($locale);
// Fallback-Chain: [user_locale, default_locale, 'en']
$fallbackChain = $localizer->getFallbackChain($locale);
```
**Locale-Extraktion**:
- Aus `ExceptionContextData::metadata['locale']`
- Fallback zu Default-Locale
- Fallback zu 'en' als letzte Option
**Integration**:
- Wird von `ExceptionMessageTranslator` verwendet
- Locale sollte in `ExceptionContextData::metadata['locale']` gespeichert werden
---
## Phase 3: Advanced Features
### 6. Exception Recovery & Retry Logic
**Ziel**: Automatische Retry-Logik für temporäre Exceptions
**Komponenten**:
- `RetryStrategy` - Retry-Strategien (Exponential Backoff, Linear, Fixed)
- `ExceptionRecoveryManager` - Recovery-Manager
- `RetryableException` - Marker-Interface
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Recovery\ExceptionRecoveryManager;
use App\Framework\ExceptionHandling\Recovery\RetryableException;
use App\Framework\Exception\ExceptionMetadata;
// Retryable Exception implementieren
final class NetworkException extends \Exception implements RetryableException
{
}
// Exception mit Retry-Config erstellen
$metadata = ExceptionMetadata::withRetry(
retryAfter: 1000 // Base delay in milliseconds
)->withMaxRetries(3)
->withRetryStrategy('exponential_backoff');
// Recovery Manager
$recoveryManager = new ExceptionRecoveryManager();
// Prüfen ob Retry nötig
if ($recoveryManager->shouldRetry($exception, $metadata)) {
$delay = $recoveryManager->getRetryDelay($exception, $metadata, $attemptNumber);
// Retry nach $delay Millisekunden
}
```
**Retry-Strategien**:
- **Exponential Backoff** (Default): `baseDelay * 2^(attempt-1)`
- **Linear**: `baseDelay * attempt`
- **Fixed**: `baseDelay` (konstant)
**ExceptionMetadata Erweiterungen**:
- `maxRetries`: Maximale Anzahl Retries (Default: 3)
- `retryStrategy`: Retry-Strategie (Default: 'exponential_backoff')
- `retryAfter`: Base Delay in Millisekunden
**Retryable Exceptions**:
- Exceptions die `RetryableException` implementieren
- Exceptions mit bestimmten Namen-Patterns (NetworkException, TimeoutException, etc.)
---
### 7. Exception Pattern Detection & Auto-Fix Suggestions
**Ziel**: ML-basierte Pattern-Erkennung mit Fix-Vorschlägen
**Komponenten**:
- `ExceptionPattern` - Value Object für Patterns
- `FixSuggestion` - Value Object für Fix-Vorschläge
- `ExceptionPatternDetector` - Pattern-Detection
**Verwendung**:
```php
use App\Framework\ExceptionHandling\PatternDetection\ExceptionPatternDetector;
use App\Framework\ExceptionHandling\PatternDetection\FixSuggestion;
// Knowledge Base definieren
$knowledgeBase = [
\App\Framework\Exception\DatabaseException::class => [
'description' => 'Database connection timeout',
'fixes' => [
[
'title' => 'Check connection pool size',
'description' => 'Increase database connection pool size',
'code' => '$config->setMaxConnections(50);',
'confidence' => 'high'
],
[
'title' => 'Check database server',
'description' => 'Verify database server is running and accessible',
'confidence' => 'medium'
]
]
]
];
// Pattern Detector erstellen
$detector = new ExceptionPatternDetector($knowledgeBase);
// Patterns erkennen
$patterns = $detector->detect($exception, $context);
foreach ($patterns as $pattern) {
echo $pattern->description . "\n";
foreach ($pattern->fixSuggestions as $fix) {
echo " - " . $fix->title . ": " . $fix->description . "\n";
}
}
```
**Integration**:
- Kann in `ErrorAggregator` integriert werden
- Patterns werden in `ExceptionContextData::metadata['patterns']` gespeichert
---
### 8. Exception Correlation & Root Cause Analysis
**Ziel**: Verknüpfung verwandter Exceptions für Root-Cause-Analyse
**Komponenten**:
- `ExceptionCorrelation` - Value Object für Korrelationen
- `ExceptionCorrelationEngine` - Correlation-Engine
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Correlation\ExceptionCorrelationEngine;
$correlationEngine = new ExceptionCorrelationEngine($cache);
// Exception korrelieren
$correlation = $correlationEngine->correlate($exception, $context);
// Correlation-Daten:
// - correlationKey: Request-ID, Session-ID oder User-ID
// - exceptionIds: Array von verwandten Exception-IDs
// - rootCauseId: ID der ersten Exception (Root Cause)
```
**Correlation-Keys**:
- **Request-ID** (höchste Priorität): Alle Exceptions in derselben Request
- **Session-ID**: Alle Exceptions in derselben Session
- **User-ID**: Alle Exceptions für denselben User
**Root Cause Analysis**:
- Erste Exception in Correlation-Chain ist Root Cause
- Alle weiteren Exceptions sind Folge-Exceptions
**Integration**:
- Correlation-Daten werden in `ExceptionContextData::metadata['correlations']` gespeichert
- Kann für Exception-Graph-Visualisierung verwendet werden
---
### 9. Exception Metrics & Monitoring Integration
**Ziel**: Integration mit Monitoring-Systemen (Prometheus, StatsD)
**Komponenten**:
- `ExceptionMetrics` - Value Object für Metriken
- `ExceptionMetricsCollector` - Metrics-Collector
- `PrometheusExporter` - Prometheus-Export
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Metrics\ExceptionMetricsCollector;
use App\Framework\ExceptionHandling\Metrics\PrometheusExporter;
$collector = new ExceptionMetricsCollector($cache);
// Exception-Metrik aufzeichnen
$collector->record($exception, $context, $executionTimeMs);
// Metriken abrufen
$metrics = $collector->getMetrics();
// Prometheus-Format exportieren
$exporter = new PrometheusExporter();
$prometheusMetrics = $exporter->export($metrics);
// Output:
// exception_total 42
// exception_by_class{exception_class="DatabaseException"} 10
// exception_by_component{component="UserService"} 5
// exception_average_execution_time_ms 125.50
```
**Metriken**:
- `totalCount`: Gesamtanzahl Exceptions
- `byClass`: Anzahl pro Exception-Klasse
- `byComponent`: Anzahl pro Component
- `averageExecutionTimeMs`: Durchschnittliche Ausführungszeit
**Integration**:
- Kann in `ProductionMetricsController` integriert werden
- Metriken werden im Prometheus-Format exportiert
- Real-time Aggregation über Time-Windows
---
### 10. Exception Health Checks & Circuit Breakers
**Ziel**: Circuit Breaker Pattern für Exception-basierte Health Checks
**Komponenten**:
- `ExceptionHealthChecker` - Health Checker
**Verwendung**:
```php
use App\Framework\ExceptionHandling\Health\ExceptionHealthChecker;
use App\Framework\ExceptionHandling\Metrics\ExceptionMetricsCollector;
$metricsCollector = new ExceptionMetricsCollector($cache);
$healthChecker = new ExceptionHealthChecker(
metricsCollector: $metricsCollector,
errorRateThreshold: 0.1, // 10% Error Rate
timeWindowSeconds: 60
);
// Health Check durchführen
$result = $healthChecker->check();
// Status:
// - Healthy: Error Rate < 5%
// - Warning: Error Rate 5-10%
// - Unhealthy: Error Rate > 10%
```
**Health Check Status**:
- **Healthy**: Error Rate unterhalb des Thresholds
- **Warning**: Error Rate bei 50% des Thresholds
- **Unhealthy**: Error Rate oberhalb des Thresholds
**Integration**:
- Implementiert `HealthCheckInterface`
- Kann in `HealthCheckManager` registriert werden
- Nutzt bestehende `CircuitBreaker` Infrastruktur
---
## DI Container Integration
### Beispiel-Konfiguration
```php
// Exception Rate Limiter
$container->bind(ExceptionRateLimitConfig::class, function() {
return ExceptionRateLimitConfig::withLimits(
maxExceptions: 10,
timeWindow: Duration::fromSeconds(60)
);
});
$container->singleton(ExceptionRateLimiter::class, function($container) {
return new ExceptionRateLimiter(
cache: $container->get(Cache::class),
config: $container->get(ExceptionRateLimitConfig::class)
);
});
// Exception Context Cache
$container->singleton(ExceptionContextCache::class, function($container) {
return new ExceptionContextCache(
cache: $container->get(Cache::class)
);
});
// Exception Context Builder
$container->singleton(ExceptionContextBuilder::class, function($container) {
return new ExceptionContextBuilder(
errorScope: $container->get(ErrorScope::class),
contextCache: $container->get(ExceptionContextCache::class)
);
});
// Exception Performance Tracker
$container->singleton(ExceptionPerformanceTracker::class, function() {
return new ExceptionPerformanceTracker();
});
// Exception Message Translator
$container->singleton(ExceptionMessageTranslator::class, function($container) {
$templates = require __DIR__ . '/config/exception_messages.php';
return new ExceptionMessageTranslator(
templates: $templates,
isDebugMode: $container->get('config')->get('app.debug', false)
);
});
// Exception Localizer
$container->singleton(ExceptionLocalizer::class, function() {
$translations = require __DIR__ . '/config/exception_translations.php';
return new ExceptionLocalizer(
translations: $translations,
defaultLocale: 'en'
);
});
// Exception Recovery Manager
$container->singleton(ExceptionRecoveryManager::class, function() {
return new ExceptionRecoveryManager();
});
// Exception Pattern Detector
$container->singleton(ExceptionPatternDetector::class, function() {
$knowledgeBase = require __DIR__ . '/config/exception_patterns.php';
return new ExceptionPatternDetector($knowledgeBase);
});
// Exception Correlation Engine
$container->singleton(ExceptionCorrelationEngine::class, function($container) {
return new ExceptionCorrelationEngine(
cache: $container->get(Cache::class)
);
});
// Exception Metrics Collector
$container->singleton(ExceptionMetricsCollector::class, function($container) {
return new ExceptionMetricsCollector(
cache: $container->get(Cache::class)
);
});
// Exception Health Checker
$container->singleton(ExceptionHealthChecker::class, function($container) {
return new ExceptionHealthChecker(
metricsCollector: $container->get(ExceptionMetricsCollector::class),
errorRateThreshold: 0.1,
timeWindowSeconds: 60
);
});
// ErrorKernel mit allen Features
$container->singleton(ErrorKernel::class, function($container) {
return new ErrorKernel(
rendererFactory: $container->get(ErrorRendererFactory::class),
reporter: $container->get(Reporter::class),
errorAggregator: $container->get(ErrorAggregatorInterface::class),
contextProvider: $container->get(ExceptionContextProvider::class),
auditLogger: $container->get(ExceptionAuditLogger::class),
rateLimiter: $container->get(ExceptionRateLimiter::class), // NEU
executionContext: $container->get(ExecutionContext::class),
consoleOutput: $container->get(ConsoleOutput::class),
isDebugMode: $container->get('config')->get('app.debug', false)
);
});
```
---
## Best Practices
### 1. Rate Limiting konfigurieren
```php
// Für Production: Strikte Limits
$config = ExceptionRateLimitConfig::withLimits(
maxExceptions: 5,
timeWindow: Duration::fromSeconds(60)
);
// Für Development: Lockerere Limits
$config = ExceptionRateLimitConfig::withLimits(
maxExceptions: 50,
timeWindow: Duration::fromSeconds(60)
);
```
### 2. Context Caching nutzen
```php
// Context Cache nur aktivieren wenn Context-Erstellung teuer ist
// (z.B. DB-Queries, externe API-Calls)
if ($needsCaching) {
$builder = new ExceptionContextBuilder(
errorScope: $errorScope,
contextCache: $contextCache
);
} else {
$builder = new ExceptionContextBuilder(errorScope: $errorScope);
}
```
### 3. User-Friendly Messages definieren
```php
// Alle wichtigen Exceptions sollten User-Friendly Messages haben
$templates = [
\App\Framework\Exception\DatabaseException::class => [
'message' => 'Database connection failed. Please try again later.',
'title' => 'Database Error',
'help' => 'If this problem persists, please contact support.'
],
\App\Framework\Exception\ValidationException::class => [
'message' => 'Please check your input and try again.',
'title' => 'Validation Error'
]
];
```
### 4. Retry-Strategien wählen
```php
// Für Network-Exceptions: Exponential Backoff
$metadata = ExceptionMetadata::withRetry(1000)
->withRetryStrategy('exponential_backoff');
// Für Rate-Limited APIs: Linear
$metadata = ExceptionMetadata::withRetry(2000)
->withRetryStrategy('linear');
// Für Polling: Fixed Delay
$metadata = ExceptionMetadata::withRetry(5000)
->withRetryStrategy('fixed');
```
### 5. Health Checks konfigurieren
```php
// Für kritische Services: Strikte Thresholds
$healthChecker = new ExceptionHealthChecker(
metricsCollector: $metricsCollector,
errorRateThreshold: 0.05, // 5%
timeWindowSeconds: 60
);
// Für weniger kritische Services: Lockerere Thresholds
$healthChecker = new ExceptionHealthChecker(
metricsCollector: $metricsCollector,
errorRateThreshold: 0.2, // 20%
timeWindowSeconds: 300
);
```
---
## Migration Guide
### Von altem System migrieren
1. **Rate Limiting aktivieren**:
```php
// In DI Container
$container->singleton(ExceptionRateLimiter::class, ...);
```
2. **Context Caching aktivieren** (optional):
```php
// Nur wenn Performance-Probleme auftreten
$container->singleton(ExceptionContextCache::class, ...);
```
3. **User-Friendly Messages hinzufügen**:
```php
// Templates in config/exception_messages.php definieren
```
4. **Health Checks registrieren**:
```php
// In HealthCheckManager
$healthCheckManager->register($exceptionHealthChecker);
```
---
## Troubleshooting
### Rate Limiting blockiert zu viele Exceptions
**Problem**: Rate Limiting blockiert auch wichtige Exceptions
**Lösung**: Threshold erhöhen oder Time Window anpassen
```php
$config = ExceptionRateLimitConfig::withLimits(
maxExceptions: 20, // Erhöht
timeWindow: Duration::fromSeconds(60)
);
```
### Context Cache liefert veraltete Daten
**Problem**: Context Cache enthält veraltete User/Session-Daten
**Lösung**: Cache bei User/Session-Änderungen invalidieren
```php
$contextCache->invalidateUser($userId);
$contextCache->invalidateSession($sessionId);
```
### Performance Tracking zeigt keine Daten
**Problem**: Performance-Metriken werden nicht aufgezeichnet
**Lösung**: Sicherstellen dass `ExceptionPerformanceTracker` in `ErrorKernel` integriert ist
```php
// Performance-Tracking manuell starten
$startData = $performanceTracker->start();
// ... exception occurs ...
$metrics = $performanceTracker->end($startData, $exception, $context);
```
---
## Weitere Ressourcen
- [Error Handling Guidelines](./error-handling.md)
- [Exception Architecture](../ERROR-HANDLING-UNIFIED-ARCHITECTURE.md)
- [Audit Logging](./audit-logging.md)

View File

@@ -0,0 +1,645 @@
# Error Handling & Debugging
This guide covers error handling patterns and debugging strategies in the framework.
## Exception Handling
All custom exceptions in the framework must extend `FrameworkException` to ensure consistent error handling, logging, and recovery mechanisms.
### The FrameworkException System
The framework provides a sophisticated exception system with:
- **ExceptionContext**: Rich context information for debugging
- **ErrorCode**: Categorized error codes with recovery hints
- **RetryAfter**: Support for recoverable operations
- **Fluent Interface**: Easy context building
### Creating Custom Exceptions
```php
namespace App\Domain\User\Exceptions;
use App\Framework\Exception\FrameworkException;
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\ExceptionContext;
final class UserNotFoundException extends FrameworkException
{
public static function byId(UserId $id): self
{
return self::create(
DatabaseErrorCode::ENTITY_NOT_FOUND,
"User with ID '{$id->toString()}' not found"
)->withData([
'user_id' => $id->toString(),
'search_type' => 'by_id'
]);
}
public static function byEmail(Email $email): self
{
$context = ExceptionContext::forOperation('user.lookup', 'UserRepository')
->withData(['email' => $email->getMasked()]);
return self::fromContext(
"User with email not found",
$context,
DatabaseErrorCode::ENTITY_NOT_FOUND
);
}
}
```
### Using ErrorCode Enums
The framework provides category-specific error code enums for better organization and type safety:
```php
use App\Framework\Exception\Core\DatabaseErrorCode;
use App\Framework\Exception\Core\AuthErrorCode;
use App\Framework\Exception\Core\HttpErrorCode;
use App\Framework\Exception\Core\SecurityErrorCode;
use App\Framework\Exception\Core\ValidationErrorCode;
// Database errors
DatabaseErrorCode::CONNECTION_FAILED
DatabaseErrorCode::QUERY_FAILED
DatabaseErrorCode::TRANSACTION_FAILED
DatabaseErrorCode::CONSTRAINT_VIOLATION
// Authentication errors
AuthErrorCode::CREDENTIALS_INVALID
AuthErrorCode::TOKEN_EXPIRED
AuthErrorCode::SESSION_EXPIRED
AuthErrorCode::ACCOUNT_LOCKED
// HTTP errors
HttpErrorCode::BAD_REQUEST
HttpErrorCode::NOT_FOUND
HttpErrorCode::METHOD_NOT_ALLOWED
HttpErrorCode::RATE_LIMIT_EXCEEDED
// Security errors
SecurityErrorCode::CSRF_TOKEN_INVALID
SecurityErrorCode::SQL_INJECTION_DETECTED
SecurityErrorCode::XSS_DETECTED
SecurityErrorCode::PATH_TRAVERSAL_DETECTED
// Validation errors
ValidationErrorCode::INVALID_INPUT
ValidationErrorCode::REQUIRED_FIELD_MISSING
ValidationErrorCode::BUSINESS_RULE_VIOLATION
ValidationErrorCode::INVALID_FORMAT
// Using error codes in exceptions:
throw FrameworkException::create(
DatabaseErrorCode::QUERY_FAILED,
"Failed to execute user query"
)->withContext(
ExceptionContext::forOperation('user.find', 'UserRepository')
->withData(['query' => 'SELECT * FROM users WHERE id = ?'])
->withDebug(['bind_params' => [$userId]])
);
```
### Exception Context Building
```php
// Method 1: Using factory methods
$exception = FrameworkException::forOperation(
'payment.process',
'PaymentService',
'Payment processing failed',
HttpErrorCode::BAD_GATEWAY
)->withData([
'amount' => $amount->toArray(),
'gateway' => 'stripe',
'customer_id' => $customerId
])->withMetadata([
'attempt' => 1,
'idempotency_key' => $idempotencyKey
]);
// Method 2: Building context separately
$context = ExceptionContext::empty()
->withOperation('order.validate', 'OrderService')
->withData([
'order_id' => $orderId,
'total' => $total->toDecimal()
])
->withDebug([
'validation_rules' => ['min_amount', 'max_items'],
'failed_rule' => 'min_amount'
]);
throw FrameworkException::fromContext(
'Order validation failed',
$context,
ValidationErrorCode::BUSINESS_RULE_VIOLATION
);
```
### Recoverable Exceptions
```php
// Creating recoverable exceptions with retry hints
final class RateLimitException extends FrameworkException
{
public static function exceeded(int $retryAfter): self
{
return self::create(
HttpErrorCode::RATE_LIMIT_EXCEEDED,
'API rate limit exceeded'
)->withRetryAfter($retryAfter)
->withData(['retry_after_seconds' => $retryAfter]);
}
}
// Using in code
try {
$response = $apiClient->request($endpoint);
} catch (RateLimitException $e) {
if ($e->isRecoverable()) {
$waitTime = $e->getRetryAfter();
// Schedule retry after $waitTime seconds
}
throw $e;
}
```
### Exception Categories
```php
// Check exception category for handling strategies
try {
$result = $operation->execute();
} catch (FrameworkException $e) {
if ($e->isCategory('AUTH')) {
// Handle authentication errors
return $this->redirectToLogin();
}
if ($e->isCategory('VAL')) {
// Handle validation errors
return $this->validationErrorResponse($e);
}
if ($e->isErrorCode(DatabaseErrorCode::CONNECTION_FAILED)) {
// Handle specific database connection errors
$this->notifyOps($e);
}
throw $e;
}
```
### Simple Exceptions for Quick Use
```php
// When you don't need the full context system
throw FrameworkException::simple('Quick error message');
// With previous exception
} catch (\PDOException $e) {
throw FrameworkException::simple(
'Database operation failed',
$e,
500
);
}
```
### Exception Data Sanitization
The framework automatically sanitizes sensitive data in exceptions:
```php
// Sensitive keys are automatically redacted
$exception->withData([
'username' => 'john@example.com',
'password' => 'secret123', // Will be logged as '[REDACTED]'
'api_key' => 'sk_live_...' // Will be logged as '[REDACTED]'
]);
```
### Best Practices
1. **Always extend FrameworkException** for custom exceptions
2. **Use ErrorCode enum** for categorizable errors
3. **Provide rich context** with operation, component, and data
4. **Use factory methods** for consistent exception creation
5. **Sanitize sensitive data** (automatic for common keys)
6. **Make exceptions domain-specific** (UserNotFoundException vs generic NotFoundException)
7. **Include recovery hints** for recoverable errors
## Unified Error Kernel Architecture
The framework uses a **context-aware error handling system** centered around the `ErrorKernel` class that automatically detects execution context (CLI vs HTTP) and handles errors accordingly.
### ErrorKernel Overview
**Location**: `src/Framework/ExceptionHandling/ErrorKernel.php`
**Key Features**:
- Automatic context detection (CLI vs HTTP)
- Colored console output for CLI errors
- HTTP Response objects for web errors
- Integration with OWASP Security Event System
- Unified error logging via LogReporter
```php
use App\Framework\ExceptionHandling\ErrorKernel;
final readonly class ErrorKernel
{
public function __construct(
private ErrorRendererFactory $rendererFactory = new ErrorRendererFactory,
private ?ExecutionContext $executionContext = null,
private ?ConsoleOutput $consoleOutput = null
) {}
/**
* Context-aware exception handler
* - CLI: Colored console output
* - HTTP: Logs error (middleware creates response)
*/
public function handle(Throwable $e, array $context = []): mixed
{
// Automatic logging
$log = new LogReporter();
$log->report($e);
// Context-aware handling
$executionContext = $this->executionContext ?? ExecutionContext::detect();
if ($executionContext->isCli()) {
$this->handleCliException($e);
return null;
}
// HTTP context - middleware will create response
return null;
}
/**
* Create HTTP Response from exception (for middleware recovery)
*/
public function createHttpResponse(
Throwable $exception,
?ExceptionContextProvider $contextProvider = null,
bool $isDebugMode = false
): Response {
$renderer = new ResponseErrorRenderer($isDebugMode);
return $renderer->createResponse($exception, $contextProvider);
}
}
```
### CLI Error Handling
**CliErrorHandler** registers global PHP error handlers for CLI context:
```php
use App\Framework\ExceptionHandling\CliErrorHandler;
use App\Framework\Console\ConsoleOutput;
// Registration in AppBootstrapper
$output = new ConsoleOutput();
$cliErrorHandler = new CliErrorHandler($output);
$cliErrorHandler->register();
// Automatic colored output for errors:
// - Red for uncaught exceptions
// - Yellow for warnings
// - Cyan for notices
// - Full stack traces in CLI
```
### HTTP Error Handling
**ExceptionHandlingMiddleware** catches exceptions in HTTP request pipeline:
```php
use App\Framework\Http\Middlewares\ExceptionHandlingMiddleware;
#[MiddlewarePriorityAttribute(MiddlewarePriority::ERROR_HANDLING)]
final readonly class ExceptionHandlingMiddleware implements HttpMiddleware
{
public function __invoke(
MiddlewareContext $context,
Next $next,
RequestStateManager $stateManager
): MiddlewareContext {
try {
return $next($context);
} catch (\Throwable $e) {
// Log exception
$this->logger->error('Unhandled exception in HTTP request', [
'exception' => get_class($e),
'message' => $e->getMessage(),
]);
// Create HTTP Response
$errorKernel = new ErrorKernel();
$response = $errorKernel->createHttpResponse(
$e,
null,
isDebugMode: false
);
return $context->withResponse($response);
}
}
}
```
### OWASP Security Event Integration
Exceptions can trigger OWASP security events for audit logging:
```php
use App\Application\Security\OWASPSecurityEventLogger;
use App\Application\Security\OWASPEventIdentifier;
// Automatic security logging
try {
$this->authenticateUser($credentials);
} catch (AuthenticationException $e) {
// ErrorKernel logs exception
$this->errorKernel->handle($e);
// OWASP event for security audit trail
$this->eventDispatcher->dispatch(
new AuthenticationFailedEvent(
OWASPEventIdentifier::AUTHN_LOGIN_FAILURE,
$credentials->username,
$e->getMessage()
)
);
throw $e;
}
```
### Legacy ErrorHandling Module Removed
**IMPORTANT**: The legacy `ErrorHandling` module (`src/Framework/ErrorHandling/`) has been **completely removed** as of the unified exception architecture migration.
**Migration Path**:
- All error handling now uses `ErrorKernel` and `FrameworkException`
- CLI errors: `CliErrorHandler``ErrorKernel`
- HTTP errors: `ExceptionHandlingMiddleware``ErrorKernel`
- Security events: Direct event dispatch via `EventDispatcher`
**Old Pattern** (removed):
```php
// ❌ Legacy - NO LONGER EXISTS
use App\Framework\ErrorHandling\ErrorHandler;
use App\Framework\ErrorHandling\SecurityEventLogger;
$errorHandler = new ErrorHandler();
$errorHandler->register();
```
**New Pattern** (current):
```php
// ✅ Unified - ErrorKernel
use App\Framework\ExceptionHandling\ErrorKernel;
$errorKernel = new ErrorKernel();
$errorKernel->handle($exception);
```
## Logging Best Practices
### Automatic Exception Logging
All exceptions handled by `ErrorKernel` are automatically logged via `LogReporter`:
```php
// Automatic logging happens in ErrorKernel::handle()
$log = new LogReporter();
$log->report($exception);
// Logs include:
// - Exception class and message
// - Stack trace
// - File and line number
// - Context data
```
### Manual Logging
```php
use App\Framework\Logging\Logger;
// Log exceptions with context
try {
$user = $this->userRepository->find($userId);
} catch (UserNotFoundException $e) {
Logger::error('User lookup failed', [
'user_id' => $userId,
'exception' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
throw $e;
}
// Log levels
Logger::debug('Debugging information');
Logger::info('Informational message');
Logger::warning('Warning condition');
Logger::error('Error condition');
Logger::critical('Critical failure');
```
## Debug Strategies
### Development vs Production
**Development** (`APP_DEBUG=true`):
- Full stack traces displayed
- Detailed error messages
- Debug data in responses
- SQL query logging
**Production** (`APP_DEBUG=false`):
- Generic error messages
- Stack traces hidden from users
- Errors logged server-side
- Security-safe responses
### Debugging Tools
```php
// Enable debug mode in ErrorKernel
$errorKernel = new ErrorKernel(
executionContext: ExecutionContext::cli(),
consoleOutput: new ConsoleOutput()
);
// HTTP Response with debug mode
$response = $errorKernel->createHttpResponse(
$exception,
$contextProvider,
isDebugMode: true // Shows stack trace in response
);
```
### Error Context Providers
```php
use App\Framework\ExceptionHandling\Context\ExceptionContextProvider;
// Attach custom context to exceptions
$contextProvider = new ExceptionContextProvider();
$contextProvider->attachContext($exception, [
'request_id' => $requestId,
'user_id' => $userId,
'operation' => 'payment.process'
]);
$response = $errorKernel->createHttpResponse(
$exception,
$contextProvider,
isDebugMode: false
);
```
## Error Recovery Patterns
### Graceful Degradation
```php
// Try primary service, fallback to secondary
try {
return $this->primaryCache->get($key);
} catch (CacheException $e) {
Logger::warning('Primary cache failed, using fallback', [
'error' => $e->getMessage()
]);
return $this->fallbackCache->get($key);
}
```
### Circuit Breaker Pattern
```php
use App\Framework\Resilience\CircuitBreaker;
$circuitBreaker = new CircuitBreaker(
failureThreshold: 5,
timeout: Duration::fromSeconds(60)
);
try {
return $circuitBreaker->call(function() {
return $this->externalApi->request($endpoint);
});
} catch (CircuitOpenException $e) {
// Circuit is open - use cached response
return $this->cachedResponse;
}
```
### Retry with Exponential Backoff
```php
use App\Framework\Queue\ValueObjects\RetryStrategy;
$retryStrategy = new ExponentialBackoffStrategy(
maxAttempts: 3,
baseDelaySeconds: 60
);
$attempt = 0;
while ($attempt < $retryStrategy->getMaxAttempts()) {
try {
return $this->performOperation();
} catch (TransientException $e) {
$attempt++;
if (!$retryStrategy->shouldRetry($attempt)) {
throw $e;
}
$delay = $retryStrategy->getDelay($attempt);
sleep($delay->toSeconds());
}
}
```
## Common Error Scenarios
### 1. Database Connection Failure
```php
try {
$connection = $this->connectionPool->getConnection();
} catch (ConnectionException $e) {
// Log error
$this->errorKernel->handle($e);
// Return cached data or error response
return $this->getCachedData() ?? $this->errorResponse();
}
```
### 2. Validation Errors
```php
try {
$user = User::create($email, $name);
} catch (ValidationException $e) {
// Return validation errors to user
return new JsonResult([
'errors' => $e->getErrors()
], status: Status::UNPROCESSABLE_ENTITY);
}
```
### 3. Authentication Failures
```php
try {
$user = $this->authenticator->authenticate($credentials);
} catch (AuthenticationException $e) {
// Log security event
$this->eventDispatcher->dispatch(
new AuthenticationFailedEvent($credentials->username)
);
// Return 401 Unauthorized
return new JsonResult([
'error' => 'Invalid credentials'
], status: Status::UNAUTHORIZED);
}
```
### 4. Resource Not Found
```php
try {
$order = $this->orderRepository->find($orderId);
} catch (OrderNotFoundException $e) {
// Return 404 Not Found
return new JsonResult([
'error' => 'Order not found'
], status: Status::NOT_FOUND);
}
```
### 5. Rate Limit Exceeded
```php
try {
$this->rateLimiter->checkLimit($userId);
} catch (RateLimitException $e) {
// Return 429 Too Many Requests with retry hint
return new JsonResult([
'error' => 'Rate limit exceeded',
'retry_after' => $e->getRetryAfter()
], status: Status::TOO_MANY_REQUESTS);
}
```

View File

@@ -106,6 +106,7 @@ That's it! The counter is now fully interactive with zero JavaScript written.
- [Security Guide](security-guide.md) - CSRF, rate limiting, input validation
- [Performance Guide](performance-guide.md) - Optimization strategies and best practices
- [Advanced Features](advanced-features.md) - Fragments, batching, SSE, optimistic UI
- [UI Integration Guide](ui-integration-guide.md) - Tooltips, loading states, dialogs, notifications
### Reference
- [API Reference](api-reference.md) - Complete API documentation

View File

@@ -0,0 +1,717 @@
# LiveComponents UI Integration Guide
**Complete Guide to UI Features: Tooltips, Loading States, Dialogs, and Notifications**
This guide covers the integrated UI features available in LiveComponents, including tooltips, skeleton loading, dialogs, modals, notifications, and loading states.
---
## Table of Contents
1. [Tooltip System](#tooltip-system)
2. [Loading States & Skeleton Loading](#loading-states--skeleton-loading)
3. [UI Helper System](#ui-helper-system)
4. [Notification Component](#notification-component)
5. [Dialog & Modal Integration](#dialog--modal-integration)
6. [Best Practices](#best-practices)
---
## Tooltip System
### Overview
The Tooltip System provides automatic tooltip initialization and management for LiveComponent elements. Tooltips are automatically initialized when components are mounted and cleaned up when components are destroyed.
**Features**:
- Automatic initialization for `data-tooltip` attributes
- Accessibility support (ARIA attributes)
- Smart positioning (viewport-aware)
- Validation error tooltips
- Automatic cleanup
### Basic Usage
```html
<!-- Simple tooltip -->
<button
data-lc-action="save"
data-tooltip="Save your changes"
>
Save
</button>
<!-- Tooltip with validation error -->
<input
type="email"
data-lc-action="validateEmail"
data-tooltip="Enter a valid email address"
data-tooltip-error="Invalid email format"
/>
```
### Server-Side Validation Tooltips
```php
use App\Framework\LiveComponents\Attributes\Action;
use App\Framework\LiveComponents\ValueObjects\LiveComponentError;
final class UserForm extends LiveComponent
{
#[Action]
public function validateEmail(string $email): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Error will automatically show tooltip if element has data-tooltip-error
throw LiveComponentError::validation(
'Invalid email format',
['field' => 'email'],
$this->id->toString(),
'validateEmail'
);
}
}
}
```
### Custom Tooltip Configuration
```javascript
// Configure tooltip behavior globally
import { tooltipManager } from './modules/livecomponent/TooltipManager.js';
// Adjust delays
tooltipManager.tooltipDelay = 500; // Show after 500ms
tooltipManager.hideDelay = 200; // Hide after 200ms
```
### Tooltip Events
```javascript
// Listen for tooltip events
window.addEventListener('livecomponent:tooltip-shown', (e) => {
const { element, tooltipText } = e.detail;
console.log(`Tooltip shown: ${tooltipText}`);
});
window.addEventListener('livecomponent:tooltip-hidden', (e) => {
const { element } = e.detail;
console.log('Tooltip hidden');
});
```
---
## Loading States & Skeleton Loading
### Overview
The Loading State System provides configurable loading indicators during LiveComponent actions, including skeleton loaders, spinners, and progress indicators.
**Features**:
- Fragment-specific loading
- Configurable loading types (skeleton, spinner, progress, none)
- Smooth transitions
- Optimistic UI integration (no loading for optimistic actions)
- Per-component configuration
### Basic Usage
```html
<!-- Component with skeleton loading -->
<div
data-live-component="product-list"
data-loading-type="skeleton"
data-loading-fragments="product-list"
>
<div data-lc-fragment="product-list">
<!-- Skeleton template will be shown during loading -->
<div class="skeleton-item">
<div class="skeleton-image"></div>
<div class="skeleton-text"></div>
</div>
</div>
</div>
```
### Server-Side Loading Configuration
```php
use App\Framework\LiveComponents\Attributes\Action;
use App\Framework\LiveComponents\Attributes\Loading;
final class ProductList extends LiveComponent
{
#[Action]
#[Loading(type: 'skeleton', fragments: ['product-list'], showDelay: 150)]
public function loadProducts(string $category): void
{
$this->products = $this->productService->getByCategory($category);
}
#[Action]
#[Loading(type: 'spinner', showDelay: 0)] // Show immediately
public function quickAction(): void
{
// Fast action with immediate spinner
}
}
```
### Loading Types
#### 1. Skeleton Loading
```html
<!-- Skeleton template in component -->
<div data-lc-fragment="content">
<!-- Default content -->
<div class="product-card">
<img src="{product.image}" />
<h3>{product.name}</h3>
</div>
<!-- Skeleton template (shown during loading) -->
<template data-skeleton-template>
<div class="product-card skeleton">
<div class="skeleton-image"></div>
<div class="skeleton-text"></div>
</div>
</template>
</div>
```
#### 2. Spinner Loading
```html
<!-- Automatic spinner overlay -->
<div
data-live-component="component-id"
data-loading-type="spinner"
>
<!-- Spinner automatically appears during actions -->
</div>
```
#### 3. Progress Loading
```html
<!-- Progress bar for long-running actions -->
<div
data-live-component="upload-component"
data-loading-type="progress"
>
<div class="progress-bar" data-progress="0"></div>
</div>
```
### Custom Loading Configuration
```javascript
// Configure loading behavior per component
const component = LiveComponentManager.getInstance().getComponent('component-id');
component.setLoadingConfig({
type: 'skeleton',
fragments: ['content', 'sidebar'],
showDelay: 150,
hideDelay: 100
});
```
### Loading Events
```javascript
// Listen for loading state changes
window.addEventListener('livecomponent:loading-started', (e) => {
const { componentId, type, fragments } = e.detail;
console.log(`Loading started: ${componentId} (${type})`);
});
window.addEventListener('livecomponent:loading-finished', (e) => {
const { componentId, duration } = e.detail;
console.log(`Loading finished: ${componentId} (${duration}ms)`);
});
```
---
## UI Helper System
### Overview
The UI Helper System provides a standardized way for LiveComponents to interact with common UI elements like dialogs, modals, and notifications.
**Features**:
- Unified API for UI components
- Integration with UIManager
- Promise-based API
- Automatic cleanup
- Component-scoped UI elements
### Dialog & Modal Helpers
```php
use App\Framework\LiveComponents\Attributes\Action;
final class UserManagement extends LiveComponent
{
#[Action]
public function showDeleteConfirm(int $userId): void
{
// Show confirmation dialog via UI Helper
$this->uiHelper->showDialog(
title: 'Delete User',
message: 'Are you sure you want to delete this user?',
buttons: [
['label' => 'Cancel', 'action' => 'cancel'],
['label' => 'Delete', 'action' => 'confirm', 'variant' => 'danger']
]
)->then(function($action) use ($userId) {
if ($action === 'confirm') {
$this->deleteUser($userId);
}
});
}
}
```
### JavaScript API
```javascript
import { LiveComponentUIHelper } from './modules/livecomponent/LiveComponentUIHelper.js';
const uiHelper = new LiveComponentUIHelper(liveComponentManager);
// Show modal
const action = await uiHelper.showModal('component-id', {
title: 'Confirm Action',
content: '<p>Are you sure?</p>',
size: 'medium',
buttons: [
{ label: 'Cancel', action: 'cancel' },
{ label: 'Confirm', action: 'confirm', variant: 'primary' }
]
});
if (action === 'confirm') {
// Handle confirmation
}
// Show alert
await uiHelper.showAlert('component-id', {
title: 'Success',
message: 'Operation completed successfully',
type: 'success'
});
// Show confirm dialog
const confirmed = await uiHelper.showConfirm('component-id', {
title: 'Delete Item',
message: 'This action cannot be undone.',
confirmText: 'Delete',
cancelText: 'Cancel'
});
```
### Notification Helpers
```javascript
// Show notification
uiHelper.showNotification('component-id', 'Operation successful', 'success');
// Show error notification with retry
uiHelper.showErrorNotification(
'component-id',
'Upload failed. Please try again.',
'error',
true, // Can retry
() => {
// Retry logic
retryUpload();
}
);
// Hide notification
uiHelper.hideNotification('component-id');
```
---
## Notification Component
### Overview
The NotificationComponent is a full-featured LiveComponent for displaying toast notifications with support for different types, positions, durations, and action buttons.
**Features**:
- Type-safe state management
- Multiple notification types (info, success, warning, error)
- Configurable positions (top-right, top-left, bottom-right, bottom-left)
- Auto-dismiss with duration
- Action buttons
- Icon support
### Basic Usage
```php
use App\Application\LiveComponents\Notification\NotificationComponent;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
final class ProductController
{
public function create(): ViewResult
{
$notification = NotificationComponent::mount(
ComponentId::generate('notification'),
message: 'Product created successfully',
type: 'success',
duration: 5000
);
return new ViewResult('product/index', [
'notification' => $notification
]);
}
}
```
### Template Integration
```html
<!-- Include notification component in layout -->
{notification}
<!-- Or use in component template -->
<div data-live-component="{notification.id}">
<!-- Notification will render here -->
</div>
```
### Server-Side Actions
```php
final class NotificationExample extends LiveComponent
{
#[Action]
public function showSuccess(): NotificationState
{
return NotificationState::empty()
->withMessage('Operation successful!', 'success')
->show();
}
#[Action]
public function showError(string $message): NotificationState
{
return NotificationState::empty()
->withMessage($message, 'error')
->show();
}
#[Action]
public function showWithAction(): NotificationState
{
return new NotificationState(
message: 'File uploaded successfully',
type: 'success',
isVisible: true,
actionText: 'View',
actionUrl: '/files'
);
}
}
```
### Client-Side API
```javascript
// Show notification via LiveComponent action
liveComponentManager.executeAction('notification-id', 'showNotification', {
message: 'Operation successful',
type: 'success',
duration: 5000
});
// Hide notification
liveComponentManager.executeAction('notification-id', 'hide');
```
### Notification Types
```php
// Info notification
$notification = NotificationState::empty()
->withMessage('New update available', 'info')
->show();
// Success notification
$notification = NotificationState::empty()
->withMessage('Changes saved', 'success')
->show();
// Warning notification
$notification = NotificationState::empty()
->withMessage('Low disk space', 'warning')
->show();
// Error notification
$notification = NotificationState::empty()
->withMessage('Upload failed', 'error')
->show();
```
### Notification Positions
```php
$notification = new NotificationState(
message: 'Notification message',
type: 'info',
position: 'top-right', // or 'top-left', 'bottom-right', 'bottom-left'
isVisible: true
);
```
### Notification with Action Button
```php
$notification = new NotificationState(
message: 'File ready for download',
type: 'success',
isVisible: true,
actionText: 'Download',
actionUrl: '/download/file.pdf'
);
```
---
## Dialog & Modal Integration
### Overview
LiveComponents integrate seamlessly with the UIManager for dialogs and modals, providing a consistent API across the application.
### Basic Modal Usage
```php
use App\Framework\LiveComponents\Attributes\Action;
final class UserSettings extends LiveComponent
{
#[Action]
public function showEditModal(int $userId): void
{
// Modal will be shown via UI Helper
$this->uiHelper->showModal(
title: 'Edit User',
content: $this->renderEditForm($userId),
size: 'large',
buttons: [
['label' => 'Save', 'action' => 'save', 'variant' => 'primary'],
['label' => 'Cancel', 'action' => 'cancel']
]
);
}
}
```
### Modal with LiveComponent Content
```php
#[Action]
public function showUserModal(int $userId): void
{
$userComponent = UserDetailsComponent::mount(
ComponentId::generate('user-details'),
userId: $userId
);
$this->uiHelper->showModal(
title: 'User Details',
content: $userComponent->render(),
size: 'medium'
);
}
```
### Modal Events
```javascript
// Listen for modal events
window.addEventListener('livecomponent:modal-opened', (e) => {
const { componentId, modalInstance } = e.detail;
console.log(`Modal opened for component: ${componentId}`);
});
window.addEventListener('livecomponent:modal-closed', (e) => {
const { componentId, action } = e.detail;
console.log(`Modal closed with action: ${action}`);
});
```
---
## Best Practices
### 1. Tooltip Usage
- **Do**: Use tooltips for helpful context and validation errors
- **Don't**: Overuse tooltips - they can be distracting
- **Accessibility**: Always ensure tooltips are keyboard-accessible
```html
<!-- Good: Helpful tooltip -->
<button data-tooltip="Save your changes (Ctrl+S)">
Save
</button>
<!-- Bad: Obvious tooltip -->
<button data-tooltip="Click to save">
Save
</button>
```
### 2. Loading States
- **Do**: Use skeleton loading for content-heavy updates
- **Do**: Use spinners for quick actions (< 500ms)
- **Don't**: Show loading for optimistic UI updates
- **Do**: Configure appropriate delays to prevent flickering
```php
// Good: Appropriate loading type
#[Loading(type: 'skeleton', fragments: ['product-list'])]
public function loadProducts(): void { }
// Good: Quick action with spinner
#[Loading(type: 'spinner', showDelay: 0)]
public function toggleFavorite(): void { }
```
### 3. Notifications
- **Do**: Use notifications for important feedback
- **Don't**: Overuse notifications - they can be annoying
- **Do**: Set appropriate durations (5s for success, longer for errors)
- **Do**: Provide action buttons for actionable notifications
```php
// Good: Clear, actionable notification
$notification = new NotificationState(
message: 'File uploaded successfully',
type: 'success',
duration: 5000,
actionText: 'View',
actionUrl: '/files'
);
// Bad: Too many notifications
// Don't show a notification for every minor action
```
### 4. Modals & Dialogs
- **Do**: Use modals for important confirmations
- **Don't**: Overuse modals - they interrupt user flow
- **Do**: Provide clear action buttons
- **Do**: Support keyboard navigation (Escape to close)
```php
// Good: Clear confirmation dialog
$this->uiHelper->showConfirm(
title: 'Delete Item',
message: 'This action cannot be undone.',
confirmText: 'Delete',
cancelText: 'Cancel'
);
```
### 5. Error Handling
- **Do**: Use ErrorBoundary for automatic error handling
- **Do**: Show user-friendly error messages
- **Do**: Provide retry options for recoverable errors
- **Don't**: Show technical error details to users
```php
// Good: User-friendly error
throw LiveComponentError::validation(
'Please enter a valid email address',
['field' => 'email'],
$this->id->toString()
);
// Bad: Technical error
throw new \Exception('Invalid email format: ' . $email);
```
---
## Configuration
### Global Configuration
```javascript
import { sharedConfig } from './modules/livecomponent/SharedConfig.js';
// Configure default values
sharedConfig.defaultDebounce = 300;
sharedConfig.defaultCacheTTL = 5000;
sharedConfig.defaultLoadingShowDelay = 150;
sharedConfig.defaultLoadingType = 'skeleton';
sharedConfig.defaultNotificationDuration = 5000;
sharedConfig.defaultNotificationPosition = 'top-right';
sharedConfig.defaultModalAnimation = 'fade';
```
### Per-Component Configuration
```html
<!-- Component-level configuration -->
<div
data-live-component="component-id"
data-loading-type="skeleton"
data-loading-show-delay="200"
data-notification-position="bottom-right"
>
<!-- Component content -->
</div>
```
---
## Troubleshooting
### Tooltips Not Showing
1. Check that `data-tooltip` attribute is present
2. Verify TooltipManager is initialized
3. Check browser console for errors
4. Ensure element is visible and not hidden
### Loading States Not Working
1. Verify `data-loading-type` attribute is set
2. Check that fragments match between HTML and PHP
3. Ensure LoadingStateManager is initialized
4. Check for JavaScript errors in console
### Notifications Not Displaying
1. Verify NotificationComponent is mounted
2. Check that component ID matches
3. Ensure state is properly serialized
4. Check browser console for errors
### Modals Not Opening
1. Verify UIManager is initialized
2. Check that modal content is valid HTML
3. Ensure no JavaScript errors are blocking execution
4. Check z-index conflicts
---
**Next**: [API Reference](api-reference.md) →

340
docs/modules/analytics.md Normal file
View File

@@ -0,0 +1,340 @@
# Analytics Module
**Unified Analytics System for Event Tracking and User Behavior**
The Analytics Module provides a comprehensive analytics system with GDPR compliance and multiple provider support.
---
## Features
- **Event Tracking** - Track custom events
- **Page View Tracking** - Automatic and manual page view tracking
- **User Behavior Tracking** - Track user interactions
- **Multiple Providers** - Support for Google Analytics, custom endpoints, and more
- **GDPR Compliance** - Consent management and data anonymization
- **Integration with LiveComponents** - Automatic tracking of LiveComponent events
- **User Identification** - Identify users for user-level analytics
---
## Quick Start
### Basic Usage
```javascript
import { Analytics } from './modules/analytics/index.js';
// Create analytics instance
const analytics = Analytics.create({
providers: ['google-analytics'],
gdprCompliant: true,
requireConsent: true
});
// Give consent (GDPR)
analytics.giveConsent();
// Track event
await analytics.track('button_click', {
button_id: 'submit',
page: '/contact'
});
// Track page view
await analytics.trackPageView('/dashboard');
```
### Module System Integration
```html
<!-- Enable global analytics -->
<script type="module">
import { init } from './modules/analytics/index.js';
init({
providers: [
{
type: 'google-analytics',
measurementId: 'G-XXXXXXXXXX'
},
{
type: 'custom',
endpoint: '/api/analytics'
}
],
gdprCompliant: true,
requireConsent: true
});
</script>
<!-- Access globally -->
<script>
// Give consent
window.Analytics.giveConsent();
// Track event
window.Analytics.track('purchase', {
value: 99.99,
currency: 'EUR'
});
</script>
```
---
## API Reference
### Analytics.create(config)
Create a new Analytics instance.
**Parameters**:
- `config.enabled` - Enable analytics (default: true)
- `config.providers` - Array of provider configs
- `config.gdprCompliant` - Enable GDPR compliance (default: true)
- `config.requireConsent` - Require user consent (default: false)
- `config.anonymizeIp` - Anonymize IP addresses (default: true)
### analytics.track(eventName, properties)
Track a custom event.
**Parameters**:
- `eventName` - Event name
- `properties` - Event properties
**Example**:
```javascript
await analytics.track('purchase', {
value: 99.99,
currency: 'EUR',
items: [{ id: 'product-1', quantity: 1 }]
});
```
### analytics.trackPageView(path, properties)
Track a page view.
**Parameters**:
- `path` - Page path (optional, defaults to current path)
- `properties` - Additional properties
### analytics.identify(userId, traits)
Identify a user.
**Parameters**:
- `userId` - User ID
- `traits` - User traits (name, email, etc.)
**Example**:
```javascript
await analytics.identify('user-123', {
name: 'John Doe',
email: 'john@example.com'
});
```
### analytics.trackBehavior(action, target, properties)
Track user behavior.
**Parameters**:
- `action` - Action type (click, scroll, etc.)
- `target` - Target element or identifier
- `properties` - Additional properties
### analytics.giveConsent()
Give GDPR consent.
### analytics.revokeConsent()
Revoke GDPR consent.
---
## Providers
### Google Analytics
```javascript
const analytics = Analytics.create({
providers: [
{
type: 'google-analytics',
measurementId: 'G-XXXXXXXXXX'
}
]
});
```
### Custom Provider
```javascript
const analytics = Analytics.create({
providers: [
{
type: 'custom',
endpoint: '/api/analytics'
}
]
});
```
### Multiple Providers
```javascript
const analytics = Analytics.create({
providers: [
'google-analytics',
{
type: 'custom',
endpoint: '/api/analytics'
}
]
});
```
---
## GDPR Compliance
### Consent Management
```javascript
const analytics = Analytics.create({
requireConsent: true,
gdprCompliant: true
});
// Show consent banner
showConsentBanner(() => {
analytics.giveConsent();
});
```
### Data Anonymization
```javascript
// IP addresses are automatically anonymized
// PII fields are automatically removed
await analytics.track('event', {
email: 'user@example.com', // Will be removed
ip: '192.168.1.1' // Will be anonymized to 192.168.1.0
});
```
---
## Integration with LiveComponents
```javascript
import { Analytics } from './modules/analytics/index.js';
import { LiveComponent } from './modules/livecomponent/index.js';
const analytics = Analytics.create();
// Track LiveComponent actions
LiveComponent.on('action-executed', (componentId, actionName, params) => {
analytics.track('livecomponent:action', {
component_id: componentId,
action: actionName,
params
});
});
// Track component updates
LiveComponent.on('component-updated', (componentId) => {
analytics.track('livecomponent:updated', {
component_id: componentId
});
});
```
---
## Use Cases
### E-commerce Tracking
```javascript
// Track purchase
await analytics.track('purchase', {
value: 99.99,
currency: 'EUR',
items: [
{ id: 'product-1', name: 'Product 1', price: 49.99, quantity: 1 },
{ id: 'product-2', name: 'Product 2', price: 50.00, quantity: 1 }
]
});
// Track add to cart
await analytics.track('add_to_cart', {
product_id: 'product-1',
value: 49.99
});
```
### User Behavior Tracking
```javascript
// Track button clicks
document.addEventListener('click', (event) => {
if (event.target.matches('[data-track]')) {
analytics.trackBehavior('click', event.target.id, {
text: event.target.textContent
});
}
});
// Track form submissions
document.addEventListener('submit', (event) => {
analytics.track('form_submit', {
form_id: event.target.id,
form_name: event.target.name
});
});
```
### Page View Tracking
```javascript
// Automatic tracking on navigation
// Or manual tracking
await analytics.trackPageView('/dashboard', {
section: 'admin',
user_role: 'admin'
});
```
---
## Best Practices
1. **Respect User Privacy** - Always get consent before tracking
2. **Anonymize Data** - Remove PII and anonymize IPs
3. **Track Meaningful Events** - Focus on business-critical events
4. **Use Consistent Naming** - Use consistent event names
5. **Monitor Performance** - Don't let analytics slow down the app
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- Fetch API
- CustomEvent support
---
**Next**: Continue with remaining modules →

View File

@@ -0,0 +1,180 @@
# Animation System Migration Guide
**Complete Migration Guide from Old Scroll Animation Modules to Unified Animation System**
This guide helps you migrate from the old scroll animation modules to the new unified Animation System.
---
## Overview
The Animation System consolidates 8 separate modules into one unified system:
- `scrollfx``AnimationSystem` (fade-in, zoom-in)
- `parallax``AnimationSystem` (parallax)
- `scroll-timeline``AnimationSystem` (timeline)
- `scroll-loop``AnimationSystem` (timeline with loop)
- `scroll-dependent``AnimationSystem` (dependent animations)
- `sticky-fade``AnimationSystem` (sticky-fade)
- `sticky-steps``AnimationSystem` (sticky-steps)
- `smooth-scroll` → Keep separate (different purpose)
---
## Migration Steps
### 1. Update Imports
**Before**:
```javascript
import { createTrigger } from './modules/scrollfx/index.js';
import { init as initParallax } from './modules/parallax/index.js';
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
```
### 2. Update Initialization
**Before**:
```javascript
createTrigger({ element: '.fade-in', offset: 0.85 });
initParallax({ selector: '.parallax' });
```
**After**:
```javascript
const system = AnimationSystem.create();
// Auto-initializes based on HTML attributes
// Or manually:
document.querySelectorAll('.fade-in').forEach(el => {
system.registerAnimation(el, { type: 'fade-in', offset: 0.85 });
});
```
### 3. Update HTML Attributes
Most HTML attributes remain compatible, but you can use new unified attributes:
**Before**:
```html
<div class="fade-in-on-scroll" data-offset="0.85">Content</div>
<div class="parallax" data-speed="0.5">Content</div>
```
**After** (still works, or use new format):
```html
<div data-animate="fade-in" data-offset="0.85">Content</div>
<div data-parallax data-speed="0.5">Content</div>
```
---
## Module-Specific Migrations
### scrollfx → AnimationSystem
**Before**:
```javascript
import { createTrigger } from './modules/scrollfx/index.js';
createTrigger({
element: '.fade-in',
offset: 0.85,
baseDelay: 0.05,
once: true
});
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
const system = AnimationSystem.create();
document.querySelectorAll('.fade-in').forEach((el, index) => {
system.registerAnimation(el, {
type: 'fade-in',
offset: 0.85,
delay: index * 0.05,
once: true
});
});
```
### parallax → AnimationSystem
**Before**:
```javascript
import { init } from './modules/parallax/index.js';
init({ selector: '.parallax', speed: 0.5 });
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
const system = AnimationSystem.create();
document.querySelectorAll('.parallax').forEach(el => {
system.registerAnimation(el, {
type: 'parallax',
speed: 0.5
});
});
```
### scroll-timeline → AnimationSystem
**Before**:
```javascript
import { init } from './modules/scroll-timeline/index.js';
init({ attribute: 'data-scroll-step', triggerPoint: 0.4 });
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
const system = AnimationSystem.create();
document.querySelectorAll('[data-scroll-step]').forEach(el => {
system.registerAnimation(el, {
type: 'timeline',
steps: parseInt(el.dataset.scrollSteps) || null,
triggerPoint: 0.4
});
});
```
---
## Backward Compatibility
The Animation System maintains backward compatibility with existing HTML:
- Old CSS classes still work: `.fade-in-on-scroll`, `.zoom-in`, `.parallax`
- Old data attributes still work: `data-parallax`, `data-scroll-step`, etc.
- Old module initialization still works (but deprecated)
---
## Breaking Changes
1. **Module Exports** - Old module exports are deprecated
2. **JavaScript API** - Some APIs have changed (see migration examples)
3. **Configuration** - Some config options have been renamed
---
## Testing Checklist
- [ ] All fade-in animations work
- [ ] All parallax effects work
- [ ] All timeline animations work
- [ ] All sticky animations work
- [ ] Performance is acceptable
- [ ] No console errors
- [ ] Backward compatibility maintained
---
## Support
For issues or questions, see the main [Animation System documentation](animation-system.md).

View File

@@ -0,0 +1,270 @@
# Animation System Module
**Unified Animation System for Scroll-Based Animations**
The Animation System Module consolidates all scroll animation modules into a single, unified system with backward compatibility.
---
## Features
- **Fade-In Animations** - Elements fade in when scrolling into view
- **Zoom-In Animations** - Elements zoom in when scrolling into view
- **Parallax Effects** - Parallax scrolling effects
- **Scroll Timeline** - Step-based scroll animations
- **Sticky Fade** - Fade effects on sticky elements
- **Sticky Steps** - Step-based animations on sticky elements
- **IntersectionObserver Support** - Efficient scroll detection
- **Backward Compatibility** - Works with existing HTML attributes
---
## Quick Start
### Basic Usage
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
// Create animation system
const system = AnimationSystem.create({
enabled: true,
useIntersectionObserver: true
});
// Register animation
system.registerAnimation(element, {
type: 'fade-in',
offset: 0.85,
delay: 0.1,
once: true
});
```
### Module System Integration
```html
<!-- Enable global animation system -->
<script type="module">
import { init } from './modules/animation-system/index.js';
init({
enabled: true,
useIntersectionObserver: true
});
</script>
<!-- Use data attributes (auto-initialized) -->
<div class="fade-in-on-scroll" data-offset="0.85" data-delay="0.1">
Content that fades in
</div>
<div data-parallax data-speed="0.5">
Parallax content
</div>
```
---
## API Reference
### AnimationSystem.create(config)
Create a new AnimationSystem instance.
**Parameters**:
- `config.enabled` - Enable animations (default: true)
- `config.useIntersectionObserver` - Use IntersectionObserver (default: true)
- `config.throttleDelay` - Throttle delay for scroll handler (default: 16ms)
### system.registerAnimation(element, config)
Register an animation for an element.
**Parameters**:
- `element` - HTMLElement
- `config.type` - Animation type
- `config.offset` - Trigger offset (0-1)
- `config.delay` - Animation delay
- `config.once` - Trigger only once
- `config.speed` - Parallax speed
- `config.steps` - Number of steps
- `config.triggerPoint` - Trigger point (0-1)
---
## Animation Types
### Fade-In
```javascript
system.registerAnimation(element, {
type: 'fade-in',
offset: 0.85,
delay: 0.1,
once: true
});
```
### Zoom-In
```javascript
system.registerAnimation(element, {
type: 'zoom-in',
offset: 0.85,
delay: 0.1
});
```
### Parallax
```javascript
system.registerAnimation(element, {
type: 'parallax',
speed: 0.5
});
```
### Timeline
```javascript
system.registerAnimation(element, {
type: 'timeline',
steps: 5,
triggerPoint: 0.4
});
```
### Sticky Fade
```javascript
system.registerAnimation(element, {
type: 'sticky-fade',
fadeStart: 0,
fadeEnd: 1
});
```
### Sticky Steps
```javascript
system.registerAnimation(element, {
type: 'sticky-steps',
steps: 3
});
```
---
## HTML Data Attributes
### Auto-Initialization
The system automatically initializes animations based on HTML attributes:
```html
<!-- Fade in -->
<div class="fade-in-on-scroll" data-offset="0.85" data-delay="0.1">
Content
</div>
<!-- Parallax -->
<div data-parallax data-speed="0.5">
Parallax content
</div>
<!-- Timeline -->
<div data-scroll-timeline data-scroll-steps="5">
Timeline content
</div>
<!-- Sticky fade -->
<div data-sticky-fade data-fade-start="0" data-fade-end="1">
Sticky content
</div>
```
---
## Backward Compatibility
The system maintains backward compatibility with old modules:
```html
<!-- Old scrollfx classes still work -->
<div class="fade-in-on-scroll">Content</div>
<div class="zoom-in">Content</div>
<!-- Old parallax attributes still work -->
<div class="parallax" data-speed="0.5">Content</div>
<!-- Old scroll-timeline attributes still work -->
<div data-scroll-step="0">Content</div>
```
---
## Migration Guide
### From scrollfx
**Before**:
```javascript
import { createTrigger } from './modules/scrollfx/index.js';
createTrigger({ element: '.fade-in', offset: 0.85 });
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
const system = AnimationSystem.create();
document.querySelectorAll('.fade-in').forEach(el => {
system.registerAnimation(el, { type: 'fade-in', offset: 0.85 });
});
```
### From parallax
**Before**:
```javascript
import { init } from './modules/parallax/index.js';
init({ selector: '.parallax' });
```
**After**:
```javascript
import { AnimationSystem } from './modules/animation-system/index.js';
const system = AnimationSystem.create();
document.querySelectorAll('.parallax').forEach(el => {
system.registerAnimation(el, { type: 'parallax', speed: 0.5 });
});
```
---
## Best Practices
1. **Use IntersectionObserver** - More efficient than scroll listeners
2. **Set Appropriate Offsets** - Balance visibility with performance
3. **Use Once for Performance** - Set `once: true` for elements that don't need to re-animate
4. **Throttle Updates** - Use appropriate throttle delays
5. **Clean Up** - Remove animations when elements are removed
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- IntersectionObserver (for efficient detection)
- requestAnimationFrame (for smooth animations)
---
**Next**: Continue with remaining modules →

View File

@@ -0,0 +1,382 @@
# Cache Manager Module
**Intelligent Caching for API Responses and Computed Values**
The Cache Manager Module provides a comprehensive caching system with multiple storage backends and caching strategies.
---
## Features
- **Memory Cache** - Fast in-memory caching
- **IndexedDB Cache** - Persistent browser storage
- **Cache Strategies** - Multiple caching strategies (cache-first, network-first, stale-while-revalidate, etc.)
- **Cache Invalidation** - Pattern-based cache invalidation
- **Cache Warming** - Preload cache values
- **Cache Analytics** - Track cache performance
- **Integration with RequestDeduplicator** - Works with LiveComponent request deduplication
---
## Quick Start
### Basic Usage
```javascript
import { CacheManager, CacheStrategy } from './modules/cache-manager/index.js';
// Create cache manager
const cache = CacheManager.create({
defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
defaultTTL: 3600000 // 1 hour
});
// Get or set value
const data = await cache.getOrSet('users', async () => {
const response = await fetch('/api/users');
return await response.json();
});
// Get from cache
const cached = await cache.get('users');
// Set in cache
await cache.set('users', data, { ttl: 1800000 }); // 30 minutes
```
### Module System Integration
```html
<!-- Enable global cache manager -->
<script type="module">
import { init } from './modules/cache-manager/index.js';
init({
defaultStrategy: 'stale-while-revalidate',
enableIndexedDB: true
});
</script>
<!-- Access globally -->
<script>
// Get or set
const data = await window.CacheManager.getOrSet('key', async () => {
return await fetch('/api/data').then(r => r.json());
});
</script>
```
---
## API Reference
### CacheManager.create(config)
Create a new CacheManager instance.
**Parameters**:
- `config.defaultStrategy` - Default caching strategy
- `config.defaultTTL` - Default time-to-live in milliseconds
- `config.maxMemorySize` - Maximum items in memory cache
- `config.enableIndexedDB` - Enable IndexedDB persistence
- `config.indexedDBName` - IndexedDB database name
- `config.enableAnalytics` - Enable cache analytics
**Example**:
```javascript
const cache = CacheManager.create({
defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
defaultTTL: 3600000,
maxMemorySize: 100,
enableIndexedDB: true
});
```
### cache.get(key, options)
Get value from cache.
**Parameters**:
- `key` - Cache key
- `options.strategy` - Caching strategy override
- `options.ttl` - Time-to-live override
**Returns**: `Promise<any | null>`
### cache.set(key, value, options)
Set value in cache.
**Parameters**:
- `key` - Cache key
- `value` - Value to cache
- `options.strategy` - Caching strategy
- `options.ttl` - Time-to-live
**Returns**: `Promise<void>`
### cache.getOrSet(key, computeFn, options)
Get value from cache or compute and cache it.
**Parameters**:
- `key` - Cache key
- `computeFn` - Function to compute value if not cached
- `options` - Cache options
**Returns**: `Promise<any>`
**Example**:
```javascript
const users = await cache.getOrSet('users', async () => {
const response = await fetch('/api/users');
return await response.json();
}, { ttl: 1800000 });
```
### cache.delete(key)
Delete value from cache.
**Parameters**:
- `key` - Cache key
**Returns**: `Promise<void>`
### cache.clear()
Clear all cache.
**Returns**: `Promise<void>`
### cache.invalidate(pattern)
Invalidate cache entries matching a pattern.
**Parameters**:
- `pattern` - String, RegExp, or function
**Returns**: `Promise<void>`
**Example**:
```javascript
// Invalidate all user-related cache
await cache.invalidate('user:');
// Invalidate with regex
await cache.invalidate(/^user:\d+$/);
// Invalidate with function
await cache.invalidate(key => key.startsWith('user:'));
```
### cache.warm(keys, computeFn)
Warm cache by preloading values.
**Parameters**:
- `keys` - Array of cache keys
- `computeFn` - Function to compute value for each key
**Returns**: `Promise<void>`
**Example**:
```javascript
await cache.warm(['user:1', 'user:2', 'user:3'], async (key) => {
const userId = key.split(':')[1];
const response = await fetch(`/api/users/${userId}`);
return await response.json();
});
```
### cache.getAnalytics()
Get cache performance analytics.
**Returns**: `CacheAnalytics`
**Example**:
```javascript
const analytics = cache.getAnalytics();
console.log(`Hit rate: ${analytics.hitRate}%`);
console.log(`Hits: ${analytics.hits}, Misses: ${analytics.misses}`);
```
---
## Cache Strategies
### Cache-First
Use cache if available, otherwise fetch.
```javascript
const data = await cache.getOrSet('key', fetchData, {
strategy: CacheStrategy.CACHE_FIRST
});
```
### Network-First
Try network first, fallback to cache.
```javascript
const data = await cache.getOrSet('key', fetchData, {
strategy: CacheStrategy.NETWORK_FIRST
});
```
### Stale-While-Revalidate
Return cache immediately, update in background.
```javascript
const data = await cache.getOrSet('key', fetchData, {
strategy: CacheStrategy.STALE_WHILE_REVALIDATE
});
```
### Network-Only
Always fetch from network, never use cache.
```javascript
const data = await cache.getOrSet('key', fetchData, {
strategy: CacheStrategy.NETWORK_ONLY
});
```
### Cache-Only
Only use cache, never fetch from network.
```javascript
const data = await cache.get('key', {
strategy: CacheStrategy.CACHE_ONLY
});
```
---
## Integration with RequestDeduplicator
```javascript
import { CacheManager } from './modules/cache-manager/index.js';
import { RequestDeduplicator } from './modules/livecomponent/RequestDeduplicator.js';
const cache = CacheManager.create();
const deduplicator = new RequestDeduplicator();
// Use cache with request deduplication
async function fetchWithCache(url) {
return await cache.getOrSet(url, async () => {
// Check for pending request
const pending = deduplicator.getPendingRequest('api', 'GET', { url });
if (pending) {
return await pending;
}
// Make request
const promise = fetch(url).then(r => r.json());
deduplicator.registerPendingRequest('api', 'GET', { url }, promise);
return await promise;
});
}
```
---
## Use Cases
### API Response Caching
```javascript
const cache = CacheManager.create({
defaultStrategy: CacheStrategy.STALE_WHILE_REVALIDATE,
defaultTTL: 300000 // 5 minutes
});
async function getUsers() {
return await cache.getOrSet('api:users', async () => {
const response = await fetch('/api/users');
return await response.json();
});
}
```
### Computed Value Caching
```javascript
const cache = CacheManager.create();
function expensiveComputation(input) {
// Expensive operation
return input * 2;
}
async function getComputedValue(input) {
const key = `computed:${input}`;
return await cache.getOrSet(key, () => expensiveComputation(input), {
ttl: 3600000 // Cache for 1 hour
});
}
```
### Cache Invalidation
```javascript
// Invalidate all user-related cache when user updates
async function updateUser(userId, data) {
await fetch(`/api/users/${userId}`, {
method: 'PUT',
body: JSON.stringify(data)
});
// Invalidate related cache
await cache.invalidate(`user:${userId}`);
await cache.invalidate('users:list');
}
```
### Cache Warming
```javascript
// Warm cache on page load
async function warmCache() {
await cache.warm(['user:1', 'user:2', 'user:3'], async (key) => {
const userId = key.split(':')[1];
const response = await fetch(`/api/users/${userId}`);
return await response.json();
});
}
```
---
## Best Practices
1. **Choose Appropriate Strategy** - Use cache-first for static data, network-first for dynamic data
2. **Set Appropriate TTL** - Balance freshness with performance
3. **Invalidate on Updates** - Clear cache when data changes
4. **Use Cache Warming** - Preload frequently accessed data
5. **Monitor Analytics** - Track cache performance and adjust strategy
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- IndexedDB (for persistent cache)
- Promise support
---
**Next**: Continue with Phase 3 modules →

View File

@@ -0,0 +1,413 @@
# Error Tracking Module
**Centralized Error Tracking and Reporting**
The Error Tracking Module provides comprehensive error tracking, grouping, and reporting capabilities for production applications.
---
## Features
- **Error Collection** - Automatically capture unhandled errors and promise rejections
- **Error Grouping** - Group similar errors to reduce noise
- **Error Reporting** - Send errors to backend for analysis
- **Error Analytics** - Track error frequency and patterns
- **Integration with ErrorBoundary** - Works with LiveComponent ErrorBoundary
- **Source Map Support** - Map minified errors to source code
- **Error Filtering** - Filter out known or irrelevant errors
- **Sampling** - Control error reporting volume with sampling
---
## Quick Start
### Basic Usage
```javascript
import { ErrorTracker } from './modules/error-tracking/index.js';
// Create error tracker
const tracker = ErrorTracker.create({
endpoint: '/api/errors',
enabled: true,
sampleRate: 1.0 // Report 100% of errors
});
// Manually capture an error
try {
// Some code that might throw
} catch (error) {
tracker.captureException(error, {
type: 'user-action',
action: 'submit-form'
});
}
```
### Module System Integration
```html
<!-- Enable global error tracking -->
<script type="module">
import { init } from './modules/error-tracking/index.js';
init({
endpoint: '/api/errors',
enabled: true,
sampleRate: 0.1 // Report 10% of errors
});
</script>
<!-- Access globally -->
<script>
// Errors are automatically captured
// Or manually capture:
window.ErrorTracker.captureException(new Error('Something went wrong'), {
context: { userId: 123 }
});
</script>
```
---
## API Reference
### ErrorTracker.create(config)
Create a new ErrorTracker instance.
**Parameters**:
- `config.endpoint` - Backend endpoint for error reporting (default: '/api/errors')
- `config.enabled` - Enable error tracking (default: true)
- `config.sampleRate` - Sampling rate 0.0 to 1.0 (default: 1.0)
- `config.maxErrors` - Maximum errors to keep in memory (default: 100)
- `config.groupingWindow` - Time window for error grouping in ms (default: 60000)
- `config.includeStack` - Include stack traces (default: true)
- `config.includeContext` - Include context information (default: true)
- `config.includeUserAgent` - Include user agent (default: true)
- `config.includeUrl` - Include current URL (default: true)
- `config.filters` - Array of filter functions or regex patterns
- `config.beforeSend` - Hook to modify errors before sending
**Example**:
```javascript
const tracker = ErrorTracker.create({
endpoint: '/api/errors',
enabled: true,
sampleRate: 0.5, // Report 50% of errors
filters: [
// Filter out specific errors
/Script error/i,
(error, context) => {
// Custom filter logic
return error.message.includes('ResizeObserver');
}
],
beforeSend: (errorData) => {
// Add additional context
errorData.userId = getCurrentUserId();
errorData.sessionId = getSessionId();
return errorData;
}
});
```
### tracker.captureException(error, context)
Manually capture an exception.
**Parameters**:
- `error` - Error object or any value
- `context` - Additional context information
**Example**:
```javascript
try {
// Some code
} catch (error) {
tracker.captureException(error, {
type: 'api-call',
endpoint: '/api/users',
method: 'POST'
});
}
```
### tracker.report()
Manually flush error reports to backend.
**Example**:
```javascript
// Report errors immediately
await tracker.report();
```
### tracker.getErrorGroups()
Get grouped errors.
**Returns**: `Array<ErrorGroup>`
**Example**:
```javascript
const groups = tracker.getErrorGroups();
groups.forEach(group => {
console.log(`${group.fingerprint}: ${group.count} occurrences`);
});
```
### tracker.getErrors()
Get all captured errors.
**Returns**: `Array<ErrorData>`
### tracker.clearErrors()
Clear all captured errors.
---
## Integration with ErrorBoundary
```javascript
import { ErrorTracker } from './modules/error-tracking/index.js';
import { ErrorBoundary } from './modules/livecomponent/ErrorBoundary.js';
const tracker = ErrorTracker.create({
endpoint: '/api/errors'
});
// ErrorBoundary automatically captures errors
const errorBoundary = new ErrorBoundary(liveComponentManager);
// Listen for errors
window.addEventListener('error-tracker:error', (event) => {
const errorData = event.detail;
console.error('Error captured:', errorData);
// Show user-friendly error message
showErrorNotification(errorData.message);
});
```
---
## Error Filtering
### Filter by Regex
```javascript
const tracker = ErrorTracker.create({
filters: [
/Script error/i, // Filter out script errors
/ResizeObserver/i // Filter out ResizeObserver errors
]
});
```
### Filter by Function
```javascript
const tracker = ErrorTracker.create({
filters: [
(error, context) => {
// Filter out errors from specific domains
if (context.url && context.url.includes('localhost')) {
return false; // Don't track localhost errors
}
return true; // Track other errors
}
]
});
```
---
## Error Sampling
Control error reporting volume with sampling:
```javascript
const tracker = ErrorTracker.create({
sampleRate: 0.1 // Report only 10% of errors
});
```
---
## beforeSend Hook
Modify errors before sending to backend:
```javascript
const tracker = ErrorTracker.create({
beforeSend: (errorData) => {
// Add user information
errorData.user = {
id: getCurrentUserId(),
email: getCurrentUserEmail()
};
// Add session information
errorData.session = {
id: getSessionId(),
startTime: getSessionStartTime()
};
// Remove sensitive data
delete errorData.context.password;
// Return modified error data
return errorData;
// Or return null/false to prevent sending
// return null;
}
});
```
---
## Error Grouping
Errors are automatically grouped by:
- Error name
- Error message
- Stack trace (first 3 lines)
Similar errors are grouped together to reduce noise:
```javascript
const groups = tracker.getErrorGroups();
groups.forEach(group => {
console.log(`Error: ${group.fingerprint}`);
console.log(`Count: ${group.count}`);
console.log(`First seen: ${new Date(group.firstSeen)}`);
console.log(`Last seen: ${new Date(group.lastSeen)}`);
});
```
---
## Backend Integration
The error tracker sends errors to the backend endpoint:
```javascript
POST /api/errors
Content-Type: application/json
{
"errors": [
{
"message": "Cannot read property 'x' of undefined",
"name": "TypeError",
"stack": "...",
"timestamp": 1234567890,
"type": "unhandled",
"context": {
"url": "https://example.com/page",
"userAgent": "...",
"viewport": { "width": 1920, "height": 1080 }
}
}
],
"errorGroups": [
{
"fingerprint": "TypeError:Cannot read property...",
"count": 5,
"firstSeen": 1234567890,
"lastSeen": 1234567900
}
]
}
```
---
## Use Cases
### Production Error Tracking
```javascript
const tracker = ErrorTracker.create({
endpoint: '/api/errors',
enabled: true,
sampleRate: 0.1, // Sample 10% in production
filters: [
// Filter out known issues
/ResizeObserver/i,
/Script error/i
],
beforeSend: (errorData) => {
// Add user context
errorData.userId = getCurrentUserId();
return errorData;
}
});
```
### Development Error Tracking
```javascript
const tracker = ErrorTracker.create({
endpoint: '/api/errors',
enabled: true,
sampleRate: 1.0, // Track all errors in development
includeStack: true,
includeContext: true
});
```
### API Error Tracking
```javascript
async function apiCall(url, options) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return await response.json();
} catch (error) {
tracker.captureException(error, {
type: 'api-error',
url,
method: options.method || 'GET',
status: error.status
});
throw error;
}
}
```
---
## Best Practices
1. **Use Sampling in Production** - Set sampleRate to 0.1 or lower to reduce backend load
2. **Filter Known Issues** - Filter out errors you can't fix (e.g., browser extensions)
3. **Add Context** - Use beforeSend to add user, session, or request context
4. **Group Errors** - Let the tracker group similar errors automatically
5. **Monitor Error Groups** - Track error frequency and patterns
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- Fetch API
- Promise support
---
**Next**: [Event Bus Module](event-bus.md) →

370
docs/modules/event-bus.md Normal file
View File

@@ -0,0 +1,370 @@
# Event Bus Module
**Centralized Event System for Cross-Module Communication**
The Event Bus Module provides a pub/sub event system for decoupled communication between modules, components, and services.
---
## Features
- **Pub/Sub Pattern** - Publish and subscribe to events
- **Namespaced Events** - Organize events with namespaces (e.g., 'user:created')
- **Event Filtering** - Filter events by data or conditions
- **Event History** - Track event history for debugging
- **Integration with LiveComponents** - Works seamlessly with LiveComponents
- **Integration with SSE** - Integrate with Server-Sent Events
- **Wildcard Support** - Subscribe to event patterns
- **Middleware Support** - Transform or filter events with middleware
---
## Quick Start
### Basic Usage
```javascript
import { EventBus } from './modules/event-bus/index.js';
// Create event bus
const bus = EventBus.create();
// Subscribe to an event
const unsubscribe = bus.on('user:created', (user) => {
console.log('User created:', user);
});
// Emit an event
bus.emit('user:created', { id: 1, name: 'John' });
// Unsubscribe
unsubscribe();
```
### Module System Integration
```html
<!-- Enable global event bus -->
<script type="module">
import { init } from './modules/event-bus/index.js';
init({
enableHistory: true,
maxHistorySize: 100
});
</script>
<!-- Access globally -->
<script>
// Subscribe
window.EventBus.on('user:created', (user) => {
console.log('User created:', user);
});
// Emit
window.EventBus.emit('user:created', { id: 1, name: 'John' });
</script>
```
---
## API Reference
### EventBus.create(config)
Create a new EventBus instance.
**Parameters**:
- `config.enableHistory` - Enable event history (default: false)
- `config.maxHistorySize` - Maximum history size (default: 100)
- `config.enableWildcards` - Enable wildcard patterns (default: true)
**Example**:
```javascript
const bus = EventBus.create({
enableHistory: true,
maxHistorySize: 50
});
```
### bus.on(eventName, callback, options)
Subscribe to an event.
**Parameters**:
- `eventName` - Event name (supports wildcards: 'user:*', '*')
- `callback` - Callback function: `(data, eventName, options) => void`
- `options.once` - Subscribe only once (default: false)
- `options.priority` - Subscription priority (default: 0)
- `options.filter` - Filter function: `(data, options) => boolean`
**Returns**: Unsubscribe function
**Example**:
```javascript
// Basic subscription
const unsubscribe = bus.on('user:created', (user) => {
console.log('User created:', user);
});
// Once subscription
bus.once('user:created', (user) => {
console.log('User created (once):', user);
});
// Priority subscription
bus.on('user:created', (user) => {
console.log('High priority handler');
}, { priority: 10 });
// Filtered subscription
bus.on('user:created', (user) => {
console.log('Admin user created');
}, {
filter: (user) => user.role === 'admin'
});
```
### bus.once(eventName, callback, options)
Subscribe to an event once (auto-unsubscribe after first emission).
**Parameters**: Same as `on()`
**Returns**: Unsubscribe function
### bus.off(eventName, callback)
Unsubscribe from an event.
**Parameters**:
- `eventName` - Event name
- `callback` - Callback function to remove
### bus.emit(eventName, data, options)
Emit an event.
**Parameters**:
- `eventName` - Event name
- `data` - Event data
- `options` - Event options
**Example**:
```javascript
bus.emit('user:created', { id: 1, name: 'John' });
bus.emit('user:updated', { id: 1, name: 'Jane' }, { source: 'api' });
```
### bus.use(middleware)
Add middleware to transform or filter events.
**Parameters**:
- `middleware` - Middleware function: `(eventName, data, options) => data | null | false`
**Example**:
```javascript
// Logging middleware
bus.use((eventName, data, options) => {
console.log(`Event: ${eventName}`, data);
return data; // Continue
});
// Filtering middleware
bus.use((eventName, data, options) => {
if (eventName.startsWith('debug:')) {
return null; // Block debug events in production
}
return data;
});
```
### bus.getHistory(filter)
Get event history.
**Parameters**:
- `filter` - Optional filter (string for event name, or function)
**Returns**: `Array<EventHistoryItem>`
**Example**:
```javascript
// Get all history
const history = bus.getHistory();
// Get history for specific event
const userHistory = bus.getHistory('user:created');
// Get history with custom filter
const recentHistory = bus.getHistory((item) => {
return Date.now() - item.timestamp < 60000; // Last minute
});
```
---
## Namespaced Events
Organize events with namespaces:
```javascript
// Subscribe to namespace
bus.on('user:*', (data, eventName) => {
console.log(`User event: ${eventName}`, data);
});
// Emit namespaced events
bus.emit('user:created', { id: 1 });
bus.emit('user:updated', { id: 1 });
bus.emit('user:deleted', { id: 1 });
```
---
## Wildcard Support
Subscribe to event patterns:
```javascript
// Subscribe to all events
bus.on('*', (data, eventName) => {
console.log(`Event: ${eventName}`, data);
});
// Subscribe to pattern
bus.on('user:*', (data, eventName) => {
console.log(`User event: ${eventName}`, data);
});
```
---
## Integration with LiveComponents
```javascript
import { EventBus } from './modules/event-bus/index.js';
import { LiveComponentManager } from './modules/livecomponent/index.js';
const bus = EventBus.create();
const lcManager = LiveComponentManager.getInstance();
// Listen for LiveComponent events
bus.on('livecomponent:action-executed', (data) => {
console.log('Action executed:', data);
});
// Emit LiveComponent events
lcManager.on('action-executed', (componentId, actionName, params) => {
bus.emit('livecomponent:action-executed', {
componentId,
actionName,
params
});
});
```
---
## Integration with SSE
```javascript
import { EventBus } from './modules/event-bus/index.js';
import { SseClient } from './modules/sse/index.js';
const bus = EventBus.create();
const sse = new SseClient(['updates']);
// Forward SSE messages to event bus
sse.on('message', (data) => {
bus.emit('sse:message', data);
});
// Listen for SSE events
bus.on('sse:message', (data) => {
console.log('SSE message:', data);
});
```
---
## Use Cases
### Module Communication
```javascript
// Module A
const bus = EventBus.create();
bus.emit('module-a:data-ready', { data: [...] });
// Module B
bus.on('module-a:data-ready', (data) => {
processData(data);
});
```
### Component Communication
```javascript
// Component A
bus.emit('component:user-selected', { userId: 123 });
// Component B
bus.on('component:user-selected', (data) => {
loadUserDetails(data.userId);
});
```
### Global Notifications
```javascript
// Emit notification
bus.emit('notification:show', {
type: 'success',
message: 'Operation completed'
});
// Listen for notifications
bus.on('notification:show', (data) => {
showNotification(data.type, data.message);
});
```
### Analytics Events
```javascript
// Track events
bus.on('*', (data, eventName) => {
// Send to analytics
analytics.track(eventName, data);
});
```
---
## Best Practices
1. **Use Namespaces** - Organize events with namespaces (e.g., 'user:created')
2. **Document Events** - Document all events and their data structures
3. **Use TypeScript** - Use TypeScript definitions for type safety
4. **Clean Up Subscriptions** - Always unsubscribe when done
5. **Use Middleware** - Use middleware for cross-cutting concerns (logging, analytics)
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- Map and Set support
---
**Next**: Continue with Phase 2 modules →

364
docs/modules/router.md Normal file
View File

@@ -0,0 +1,364 @@
# Router Enhancement Module
**Enhanced Routing with Guards, Middleware, and Analytics**
The Router Enhancement Module provides advanced routing capabilities with access control, middleware, lazy loading, and analytics.
---
## Features
- **Route Guards** - Access control for routes (auth, permissions, roles)
- **Route Middleware** - Cross-cutting concerns (analytics, loading, etc.)
- **Lazy Route Loading** - Load routes on demand
- **Route Analytics** - Track navigation patterns
- **Integration with LiveComponents** - Seamless integration with LiveComponent system
- **History & Hash Modes** - Support for both history and hash routing
---
## Quick Start
### Basic Usage
```javascript
import { Router, BuiltInGuards, BuiltInMiddleware } from './modules/router/index.js';
// Create router
const router = Router.create({
mode: 'history',
base: '/',
enableAnalytics: true
});
// Register routes
router.routes([
{
path: '/',
component: () => '<div>Home</div>',
name: 'home',
title: 'Home'
},
{
path: '/dashboard',
component: () => '<div>Dashboard</div>',
name: 'dashboard',
title: 'Dashboard',
guards: ['auth'],
middleware: ['analytics', 'loading']
},
{
path: '/admin',
component: () => import('./components/Admin.js'),
name: 'admin',
title: 'Admin',
guards: ['auth', 'role:admin'],
lazy: true
}
]);
// Register guards
router.guard('auth', async (to, from) => {
const isAuthenticated = await checkAuth();
if (!isAuthenticated) {
return '/login'; // Redirect to login
}
return true; // Allow navigation
});
// Add global middleware
router.use(BuiltInMiddleware.analytics);
router.use(BuiltInMiddleware.scrollToTop);
// Navigate
await router.navigate('/dashboard');
```
---
## API Reference
### Router.create(config)
Create a new Router instance.
**Parameters**:
- `config.mode` - Routing mode: 'history' or 'hash'
- `config.base` - Base path
- `config.enableAnalytics` - Enable route analytics
### router.route(path, config)
Register a single route.
**Parameters**:
- `path` - Route path
- `config.component` - Component (string, function, or HTMLElement)
- `config.name` - Route name
- `config.title` - Page title
- `config.guards` - Array of guard names
- `config.middleware` - Array of middleware
- `config.lazy` - Lazy load component
### router.guard(name, guardFn)
Register a route guard.
**Parameters**:
- `name` - Guard name
- `guardFn` - Guard function: `(to, from, context) => boolean | string`
### router.use(middleware)
Add global middleware.
**Parameters**:
- `middleware` - Middleware instance, function, or built-in name
### router.beforeEach(hook)
Add before navigation hook.
**Parameters**:
- `hook` - Hook function: `(to, from) => boolean | string | void`
### router.afterEach(hook)
Add after navigation hook.
**Parameters**:
- `hook` - Hook function: `(to, from) => void`
### router.navigate(path, options)
Navigate to a route.
**Parameters**:
- `path` - Route path
- `options.container` - Container element
- `options.updateHistory` - Update browser history
**Returns**: `Promise<boolean>`
---
## Route Guards
### Authentication Guard
```javascript
router.guard('auth', async (to, from) => {
if (!isAuthenticated()) {
return '/login';
}
return true;
});
// Use in route
router.route('/dashboard', {
component: DashboardComponent,
guards: ['auth']
});
```
### Role Guard
```javascript
router.guard('admin', async (to, from) => {
if (getUserRole() !== 'admin') {
return '/unauthorized';
}
return true;
});
// Use in route
router.route('/admin', {
component: AdminComponent,
guards: ['auth', 'admin']
});
```
### Built-in Guards
```javascript
// Use built-in guards
router.route('/dashboard', {
component: DashboardComponent,
guards: ['auth'] // Uses BuiltInGuards.auth
});
router.route('/login', {
component: LoginComponent,
guards: ['guest'] // Uses BuiltInGuards.guest
});
```
---
## Route Middleware
### Analytics Middleware
```javascript
// Use built-in analytics middleware
router.use('analytics');
// Or custom middleware
router.use(RouteMiddleware.create('custom', async (to, from, next) => {
// Track navigation
analytics.track('page_view', { path: to.path });
next();
}));
```
### Loading Middleware
```javascript
router.use('loading'); // Shows loading indicator during navigation
```
### Scroll to Top Middleware
```javascript
router.use('scroll-to-top'); // Scrolls to top after navigation
```
---
## Lazy Route Loading
```javascript
router.route('/admin', {
component: () => import('./components/Admin.js'),
lazy: true
});
// Or with dynamic import
router.route('/user/:id', {
component: async (route) => {
const UserComponent = await import('./components/User.js');
return UserComponent.default(route.params.id);
},
lazy: true
});
```
---
## Integration with LiveComponents
```javascript
import { Router } from './modules/router/index.js';
import { LiveComponent } from './modules/livecomponent/index.js';
const router = Router.create();
router.route('/dashboard', {
component: async (route) => {
// Initialize LiveComponents after navigation
const container = document.querySelector('main');
container.innerHTML = '<div data-live-component="dashboard"></div>';
// Initialize LiveComponent
const component = container.querySelector('[data-live-component]');
LiveComponent.init(component);
return container;
}
});
```
---
## Route Analytics
```javascript
const router = Router.create({ enableAnalytics: true });
// Get analytics
const analytics = router.getAnalytics();
console.log('Total navigations:', analytics.totalNavigations);
console.log('Navigation history:', analytics.navigations);
// Listen for navigation events
window.addEventListener('router:navigation', (event) => {
const { to, from, timestamp } = event.detail;
console.log(`Navigated from ${from} to ${to}`);
});
```
---
## Use Cases
### Protected Routes
```javascript
router.routes([
{
path: '/',
component: HomeComponent,
name: 'home'
},
{
path: '/dashboard',
component: DashboardComponent,
name: 'dashboard',
guards: ['auth']
},
{
path: '/admin',
component: AdminComponent,
name: 'admin',
guards: ['auth', 'admin']
}
]);
```
### Route with Middleware
```javascript
router.route('/api-data', {
component: ApiDataComponent,
middleware: ['analytics', 'loading']
});
```
### Lazy Loading
```javascript
router.route('/heavy-page', {
component: () => import('./pages/HeavyPage.js'),
lazy: true,
guards: ['auth']
});
```
---
## Best Practices
1. **Use Guards for Access Control** - Protect routes with guards
2. **Use Middleware for Cross-Cutting Concerns** - Analytics, loading, etc.
3. **Lazy Load Heavy Routes** - Improve initial load time
4. **Track Navigation** - Use analytics to understand user behavior
5. **Handle Errors** - Provide fallback routes for errors
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- History API (for history mode)
- Promise support
---
**Next**: [Analytics Module](analytics.md) →

382
docs/modules/security.md Normal file
View File

@@ -0,0 +1,382 @@
# Security Module
**Security Utilities: CSRF, XSS Protection, and CSP Helpers**
The Security Module provides comprehensive security utilities for client-side security management.
---
## Features
- **CSRF Token Management** - Automatic token refresh and management
- **XSS Protection** - HTML sanitization and input validation
- **Content Security Policy** - CSP validation and helpers
- **Security Headers Validation** - Client-side security header checks
---
## Quick Start
### Basic Usage
```javascript
import { SecurityManager } from './modules/security/index.js';
// Create security manager
const security = SecurityManager.create({
csrf: {
autoRefresh: true,
refreshInterval: 30 * 60 * 1000 // 30 minutes
},
xss: {
enabled: true,
sanitizeOnInput: false
}
});
// Get CSRF token
const token = security.getCsrfToken();
// Use in fetch request
const response = await fetch('/api/endpoint', {
method: 'POST',
headers: {
...security.getCsrfTokenHeader(),
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
```
### Module System Integration
```html
<!-- Enable global security manager -->
<script type="module">
import { init } from './modules/security/index.js';
init({
csrf: {
autoRefresh: true
}
});
</script>
<!-- Access globally -->
<script>
// Get CSRF token
const token = window.SecurityManager.getCsrfToken();
// Refresh token
await window.SecurityManager.refreshCsrfToken();
</script>
```
---
## API Reference
### SecurityManager.create(config)
Create a new SecurityManager instance.
**Parameters**:
- `config.csrf` - CSRF manager configuration
- `config.xss` - XSS protection configuration
- `config.csp` - CSP configuration
**Example**:
```javascript
const security = SecurityManager.create({
csrf: {
tokenName: '_token',
headerName: 'X-CSRF-TOKEN',
autoRefresh: true,
refreshInterval: 30 * 60 * 1000
},
xss: {
enabled: true,
sanitizeOnInput: false
}
});
```
### security.getCsrfToken()
Get current CSRF token.
**Returns**: `string | null`
### security.getCsrfTokenHeader()
Get CSRF token header object for use in fetch requests.
**Returns**: `Record<string, string>`
**Example**:
```javascript
const headers = {
...security.getCsrfTokenHeader(),
'Content-Type': 'application/json'
};
```
### security.refreshCsrfToken()
Manually refresh CSRF token.
**Returns**: `Promise<void>`
### security.escapeHtml(text)
Escape HTML to prevent XSS.
**Parameters**:
- `text` - Text to escape
**Returns**: `string`
**Example**:
```javascript
const safe = security.escapeHtml('<script>alert("xss")</script>');
// Returns: &lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;
```
### security.validateUrl(url)
Validate URL to prevent XSS.
**Parameters**:
- `url` - URL to validate
**Returns**: `boolean`
**Example**:
```javascript
if (security.validateUrl(userInput)) {
// Safe to use
} else {
// Potentially dangerous
}
```
### security.validateSecurityHeaders()
Validate security headers.
**Returns**: `SecurityHeadersValidation`
**Example**:
```javascript
const validation = security.validateSecurityHeaders();
if (!validation.valid) {
console.warn('Security issues:', validation.issues);
}
```
---
## CSRF Token Management
### Automatic Token Refresh
```javascript
const security = SecurityManager.create({
csrf: {
autoRefresh: true,
refreshInterval: 30 * 60 * 1000 // Refresh every 30 minutes
}
});
```
### Manual Token Refresh
```javascript
await security.refreshCsrfToken();
```
### Using Token in Requests
```javascript
// Get token header
const headers = security.getCsrfTokenHeader();
// Use in fetch
const response = await fetch('/api/endpoint', {
method: 'POST',
headers: {
...headers,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
```
---
## XSS Protection
### HTML Sanitization
```javascript
const security = SecurityManager.create({
xss: {
enabled: true,
sanitizeOnInput: true // Auto-sanitize on input
}
});
// Manual sanitization
const safe = security.sanitizeHtml(userInput);
```
### HTML Escaping
```javascript
const escaped = security.escapeHtml('<script>alert("xss")</script>');
```
### URL Validation
```javascript
if (security.validateUrl(userInput)) {
// Safe URL
window.location.href = userInput;
} else {
// Potentially dangerous
console.error('Invalid URL');
}
```
---
## Content Security Policy
### CSP Validation
```javascript
const security = SecurityManager.create({
csp: {
enabled: true
}
});
// CSP is automatically validated on init
// Check validation results
const validation = security.validateSecurityHeaders();
```
---
## Integration with LiveComponents
```javascript
import { SecurityManager } from './modules/security/index.js';
import { LiveComponentManager } from './modules/livecomponent/index.js';
const security = SecurityManager.create();
// LiveComponents automatically use CSRF tokens
// But you can also manually update tokens
security.csrfManager.updateAllTokens();
```
---
## Integration with Forms
```javascript
import { SecurityManager } from './modules/security/index.js';
const security = SecurityManager.create();
// Forms automatically get updated CSRF tokens
// Listen for token refresh events
window.addEventListener('csrf:token-refreshed', (event) => {
console.log('CSRF token refreshed:', event.detail.token);
});
```
---
## Use Cases
### API Requests with CSRF
```javascript
const security = SecurityManager.create();
async function apiCall(url, data) {
const response = await fetch(url, {
method: 'POST',
headers: {
...security.getCsrfTokenHeader(),
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
```
### User Input Sanitization
```javascript
const security = SecurityManager.create();
function handleUserInput(input) {
// Sanitize HTML
const sanitized = security.sanitizeHtml(input);
// Escape for display
const escaped = security.escapeHtml(input);
// Validate URL
if (security.validateUrl(input)) {
// Safe to use as URL
}
}
```
### Security Headers Check
```javascript
const security = SecurityManager.create();
// Validate security headers
const validation = security.validateSecurityHeaders();
if (!validation.valid) {
console.warn('Security issues detected:', validation.issues);
// Report to backend or show warning
}
```
---
## Best Practices
1. **Always Use CSRF Tokens** - Include CSRF tokens in all state-changing requests
2. **Sanitize User Input** - Sanitize HTML before displaying user content
3. **Validate URLs** - Always validate URLs before using them
4. **Enable Auto-Refresh** - Keep CSRF tokens fresh with auto-refresh
5. **Check Security Headers** - Validate security headers in development
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- Fetch API
- CustomEvent support
---
**Next**: [Cache Manager Module](cache-manager.md) →

View File

@@ -0,0 +1,397 @@
# State Manager Module
**Centralized, Reactive State Management for Client-Side State**
The State Manager Module provides a centralized state management system similar to Redux or Vuex, with support for state persistence, cross-tab synchronization, and integration with LiveComponents.
---
## Features
- **Reactive State Store** - Subscribe to state changes and react automatically
- **State Persistence** - Automatically save and restore state from localStorage or sessionStorage
- **Cross-Tab Synchronization** - Keep state synchronized across browser tabs
- **Integration with LiveComponents** - Seamless integration with LiveComponent state
- **Time-Travel Debugging** - Debug state changes with history and time-travel
- **Middleware Support** - Extend functionality with custom middleware
---
## Quick Start
### Basic Usage
```javascript
import { StateManager } from './modules/state-manager/index.js';
// Create a state manager
const store = StateManager.create({
initialState: {
user: { name: '', email: '' },
cart: { items: [], total: 0 },
ui: { sidebarOpen: false }
}
});
// Set state
store.set('user.name', 'John Doe');
store.set('cart.items', [{ id: 1, name: 'Product' }]);
// Get state
const userName = store.get('user.name');
const cartItems = store.get('cart.items', []);
// Subscribe to changes
const unsubscribe = store.subscribe('cart.items', (items) => {
console.log('Cart items changed:', items);
updateCartUI(items);
});
// Unsubscribe
unsubscribe();
```
### Module System Integration
```html
<!-- Enable global state manager -->
<script type="module">
import { init } from './modules/state-manager/index.js';
init({
initialState: {
user: {},
cart: {}
},
persistence: {
enabled: true,
storage: 'localStorage',
key: 'app-state'
}
});
</script>
<!-- Access globally -->
<script>
window.StateManager.set('user.name', 'John');
const name = window.StateManager.get('user.name');
</script>
```
---
## API Reference
### StateManager.create(config)
Create a new StateManager instance.
**Parameters**:
- `config.initialState` - Initial state object
- `config.maxHistorySize` - Maximum history size (default: 50)
- `config.enableHistory` - Enable history for time-travel (default: false)
- `config.persistence.enabled` - Enable state persistence (default: false)
- `config.persistence.storage` - Storage type: 'localStorage' or 'sessionStorage' (default: 'localStorage')
- `config.persistence.key` - Storage key (default: 'app-state')
- `config.persistence.paths` - Array of paths to persist (empty = all)
- `config.sync.enabled` - Enable cross-tab synchronization (default: false)
**Example**:
```javascript
const store = StateManager.create({
initialState: { user: {}, cart: {} },
persistence: {
enabled: true,
storage: 'localStorage',
paths: ['user', 'cart'] // Only persist these paths
},
sync: {
enabled: true // Sync across tabs
}
});
```
### store.getState()
Get the entire state object.
**Returns**: `Record<string, any>`
### store.get(path, defaultValue)
Get state at a specific path.
**Parameters**:
- `path` - Dot-separated path (e.g., 'user.name')
- `defaultValue` - Default value if path doesn't exist
**Returns**: `any`
**Example**:
```javascript
const userName = store.get('user.name', 'Guest');
const cartTotal = store.get('cart.total', 0);
```
### store.set(path, value)
Set state at a specific path.
**Parameters**:
- `path` - Dot-separated path
- `value` - Value to set
**Example**:
```javascript
store.set('user.name', 'John Doe');
store.set('cart.items', [{ id: 1, name: 'Product' }]);
```
### store.dispatch(action)
Dispatch an action (Redux-style).
**Parameters**:
- `action` - Action object with `type` property, or a thunk function
**Example**:
```javascript
// Simple action
store.dispatch({
type: 'ADD_TO_CART',
productId: 123,
quantity: 1
});
// Thunk (async action)
store.dispatch(async (dispatch, getState) => {
const response = await fetch('/api/products');
const products = await response.json();
dispatch({ type: 'SET_PRODUCTS', products });
});
```
### store.subscribe(path, callback)
Subscribe to state changes at a specific path.
**Parameters**:
- `path` - Dot-separated path, or '*' for all changes
- `callback` - Callback function: `(newValue, oldValue, path) => void`
**Returns**: Unsubscribe function
**Example**:
```javascript
const unsubscribe = store.subscribe('cart.items', (items, oldItems, path) => {
console.log(`Cart items changed at ${path}:`, items);
updateCartUI(items);
});
// Later...
unsubscribe();
```
### store.subscribeAll(callback)
Subscribe to all state changes.
**Parameters**:
- `callback` - Callback function: `(state) => void`
**Returns**: Unsubscribe function
### store.use(middleware)
Add middleware to the state manager.
**Parameters**:
- `middleware` - Middleware function: `(action, getState) => action | null`
**Example**:
```javascript
// Logging middleware
store.use((action, getState) => {
console.log('Action:', action);
console.log('Current state:', getState());
return action; // Return action to continue, or null to block
});
// Validation middleware
store.use((action, getState) => {
if (action.type === 'SET' && action.path === 'user.email') {
if (!isValidEmail(action.value)) {
console.error('Invalid email');
return null; // Block the action
}
}
return action;
});
```
### store.getHistory()
Get action history for time-travel debugging.
**Returns**: `Array<HistoryPoint>`
### store.timeTravel(index)
Time-travel to a specific history point.
**Parameters**:
- `index` - History index
### store.reset()
Reset state to initial state.
### store.destroy()
Destroy the state manager and clean up resources.
---
## Integration with LiveComponents
```javascript
import { StateManager } from './modules/state-manager/index.js';
import { LiveComponentManager } from './modules/livecomponent/index.js';
const store = StateManager.create();
const lcManager = LiveComponentManager.getInstance();
// Sync LiveComponent state with StateManager
lcManager.on('component:state-updated', (componentId, state) => {
store.set(`livecomponents.${componentId}`, state);
});
// Update LiveComponent from StateManager
store.subscribe('livecomponents', (state) => {
Object.entries(state).forEach(([componentId, componentState]) => {
lcManager.updateComponentState(componentId, componentState);
});
});
```
---
## Use Cases
### User Preferences
```javascript
const store = StateManager.create({
initialState: {
preferences: {
theme: 'light',
language: 'en',
notifications: true
}
},
persistence: {
enabled: true,
storage: 'localStorage',
paths: ['preferences']
}
});
// Save preference
store.set('preferences.theme', 'dark');
// Load preference
const theme = store.get('preferences.theme', 'light');
```
### Shopping Cart
```javascript
const store = StateManager.create({
initialState: {
cart: {
items: [],
total: 0
}
},
persistence: {
enabled: true,
storage: 'sessionStorage',
paths: ['cart']
},
sync: {
enabled: true // Sync cart across tabs
}
});
// Add item
store.set('cart.items', [
...store.get('cart.items', []),
{ id: 1, name: 'Product', price: 99.99 }
]);
// Calculate total
store.subscribe('cart.items', (items) => {
const total = items.reduce((sum, item) => sum + item.price, 0);
store.set('cart.total', total);
});
```
### UI State
```javascript
const store = StateManager.create({
initialState: {
ui: {
sidebarOpen: false,
modalOpen: false,
activeTab: 'home'
}
}
});
// Toggle sidebar
store.set('ui.sidebarOpen', !store.get('ui.sidebarOpen'));
// Subscribe to UI changes
store.subscribe('ui', (uiState) => {
updateUI(uiState);
});
```
---
## Best Practices
1. **Use Scoped State Managers** - Create separate state managers for different features
2. **Persist Only Necessary Data** - Use `paths` to limit what gets persisted
3. **Use Middleware for Cross-Cutting Concerns** - Logging, validation, etc.
4. **Subscribe Selectively** - Only subscribe to paths you need
5. **Clean Up Subscriptions** - Always call unsubscribe when done
---
## Performance Considerations
- State updates are synchronous and immediate
- Subscriptions are called synchronously (be careful with expensive operations)
- Persistence is debounced internally
- Cross-tab sync uses BroadcastChannel (efficient)
---
## Browser Support
- **Chrome/Edge**: 38+
- **Firefox**: 38+
- **Safari**: 15.4+
- **Mobile**: iOS 15.4+, Android Chrome 38+
**Required Features**:
- ES2020 JavaScript
- BroadcastChannel (for cross-tab sync)
- localStorage/sessionStorage (for persistence)
---
**Next**: [Validation Module](validation.md) →

462
docs/modules/validation.md Normal file
View File

@@ -0,0 +1,462 @@
# Validation Module
**Standalone Validation System for Fields, Forms, and Data**
The Validation Module provides a comprehensive validation system that can be used independently or integrated with form-handling and LiveComponents.
---
## Features
- **Schema-Based Validation** - Define validation rules in a schema
- **Field-Level Validation** - Validate individual fields
- **Async Validation** - Support for asynchronous validation (e.g., API checks)
- **Custom Validation Rules** - Register your own validation rules
- **Integration with form-handling** - Works seamlessly with form-handling module
- **Integration with LiveComponents** - Validate LiveComponent data
- **HTML5 Attribute Support** - Automatically reads validation rules from HTML attributes
---
## Quick Start
### Basic Usage
```javascript
import { Validator } from './modules/validation/index.js';
// Create validator with schema
const validator = Validator.create({
email: ['required', 'email'],
age: [
'required',
'number',
{ rule: 'min', options: { value: 18 } },
{ rule: 'max', options: { value: 100 } }
],
password: [
'required',
{ rule: 'minLength', options: { value: 8 } }
]
});
// Validate data
const result = await validator.validate({
email: 'user@example.com',
age: 25,
password: 'secret123'
});
if (result.valid) {
console.log('Validation passed');
} else {
console.log('Validation errors:', result.errors);
}
```
### From HTML Form
```javascript
import { Validator } from './modules/validation/index.js';
// Create validator from form element
const form = document.querySelector('#my-form');
const validator = Validator.fromForm(form);
// Validate form data
const formData = new FormData(form);
const data = Object.fromEntries(formData);
const result = await validator.validate(data);
```
---
## API Reference
### Validator.create(schema)
Create a new Validator instance with a schema.
**Parameters**:
- `schema` - Validation schema object
**Example**:
```javascript
const validator = Validator.create({
email: 'email',
age: ['required', 'number', { rule: 'min', options: { value: 18 } }]
});
```
### Validator.fromForm(form)
Create a validator from an HTML form element, reading validation rules from HTML attributes.
**Parameters**:
- `form` - HTMLFormElement
**Example**:
```html
<form id="my-form">
<input type="email" name="email" required />
<input type="number" name="age" min="18" max="100" required />
<input type="password" name="password" minlength="8" required />
</form>
```
```javascript
const form = document.querySelector('#my-form');
const validator = Validator.fromForm(form);
```
### validator.validate(data)
Validate entire data object against schema.
**Parameters**:
- `data` - Data object to validate
**Returns**: `Promise<ValidationResults>`
**Example**:
```javascript
const result = await validator.validate({
email: 'user@example.com',
age: 25
});
console.log(result.valid); // true or false
console.log(result.errors); // { email: ['...'], age: ['...'] }
```
### validator.validateField(fieldName, value)
Validate a single field.
**Parameters**:
- `fieldName` - Field name
- `value` - Field value
**Returns**: `Promise<ValidationResult>`
**Example**:
```javascript
const result = await validator.validateField('email', 'user@example.com');
console.log(result.valid); // true or false
console.log(result.errors); // ['error message']
```
### validator.validateFields(data, fieldNames)
Validate specific fields.
**Parameters**:
- `data` - Data object
- `fieldNames` - Array of field names to validate
**Returns**: `Promise<ValidationResults>`
### validator.registerRule(name, rule)
Register a custom validation rule.
**Parameters**:
- `name` - Rule name
- `rule` - Validation function: `(value, options) => boolean | string`
**Example**:
```javascript
validator.registerRule('customRule', (value, options) => {
if (value === options.expected) {
return true;
}
return options.message || 'Validation failed';
});
// Use custom rule
const validator = Validator.create({
field: { rule: 'customRule', options: { expected: 'test', message: 'Must be "test"' } }
});
```
---
## Built-in Validation Rules
### required
Field must have a value.
```javascript
email: 'required'
// or
email: { rule: 'required', options: { message: 'Email is required' } }
```
### email
Valid email address format.
```javascript
email: 'email'
```
### url
Valid URL format.
```javascript
website: 'url'
```
### min / max
Minimum/maximum numeric value.
```javascript
age: [
{ rule: 'min', options: { value: 18 } },
{ rule: 'max', options: { value: 100 } }
]
```
### minLength / maxLength
Minimum/maximum string length.
```javascript
password: [
{ rule: 'minLength', options: { value: 8 } },
{ rule: 'maxLength', options: { value: 128 } }
]
```
### pattern
Regex pattern validation.
```javascript
username: {
rule: 'pattern',
options: {
value: '^[a-zA-Z0-9_]+$',
message: 'Username can only contain letters, numbers, and underscores'
}
}
```
### number
Must be a valid number.
```javascript
price: 'number'
```
### integer
Must be an integer.
```javascript
quantity: 'integer'
```
### phone
Valid phone number format.
```javascript
phone: 'phone'
```
### postalCode
Valid postal code (supports DE, US, UK, FR).
```javascript
postalCode: {
rule: 'postalCode',
options: { country: 'DE' }
}
```
### custom
Custom validation function.
```javascript
field: {
rule: 'custom',
options: {
validator: (value, options) => {
// Custom validation logic
return value === options.expected ? true : 'Value must be ' + options.expected;
},
expected: 'test'
}
}
```
---
## Async Validation
```javascript
const validator = Validator.create({
email: {
rule: 'custom',
async: true,
validator: async (value, options) => {
// Check if email exists via API
const response = await fetch(`/api/check-email?email=${value}`);
const data = await response.json();
if (data.exists) {
return 'Email already exists';
}
return true;
}
}
});
const result = await validator.validate({ email: 'user@example.com' });
```
---
## Integration with form-handling
```javascript
import { Validator } from './modules/validation/index.js';
import { FormHandler } from './modules/form-handling/index.js';
const form = document.querySelector('#my-form');
const validator = Validator.fromForm(form);
const formHandler = FormHandler.create(form);
// Use validator with form handler
formHandler.validator = validator;
```
---
## Integration with LiveComponents
```javascript
import { Validator } from './modules/validation/index.js';
import { LiveComponentManager } from './modules/livecomponent/index.js';
const validator = Validator.create({
email: ['required', 'email'],
name: ['required', { rule: 'minLength', options: { value: 2 } }]
});
// Validate before action
const lcManager = LiveComponentManager.getInstance();
lcManager.on('action:before-execute', async (componentId, actionName, params) => {
if (actionName === 'submitForm') {
const result = await validator.validate(params);
if (!result.valid) {
// Handle validation errors
return false; // Prevent action
}
}
});
```
---
## Use Cases
### Form Validation
```javascript
const validator = Validator.create({
email: ['required', 'email'],
password: [
'required',
{ rule: 'minLength', options: { value: 8 } }
],
confirmPassword: [
'required',
{
rule: 'custom',
validator: (value, options) => {
const password = options.password;
return value === password ? true : 'Passwords do not match';
},
options: { password: formData.password }
}
]
});
```
### API Response Validation
```javascript
const validator = Validator.create({
id: ['required', 'integer'],
name: ['required', { rule: 'minLength', options: { value: 1 } }],
email: ['required', 'email']
});
// Validate API response
const response = await fetch('/api/user');
const data = await response.json();
const result = await validator.validate(data);
if (!result.valid) {
console.error('Invalid API response:', result.errors);
}
```
### User Input Validation
```javascript
// Validate on input
const validator = Validator.create({
search: {
rule: 'minLength',
options: { value: 3, message: 'Search must be at least 3 characters' }
}
});
const input = document.querySelector('#search');
input.addEventListener('input', async (e) => {
const result = await validator.validateField('search', e.target.value);
if (!result.valid) {
showError(result.errors[0]);
} else {
hideError();
}
});
```
---
## Best Practices
1. **Use Schema-Based Validation** - Define validation rules in a schema for reusability
2. **Register Custom Rules** - Create reusable custom validation rules
3. **Validate Early** - Validate on blur or input for better UX
4. **Show Clear Errors** - Display validation errors clearly to users
5. **Use Async Validation Sparingly** - Only for necessary checks (e.g., email uniqueness)
---
## Browser Support
- **Chrome/Edge**: 90+
- **Firefox**: 88+
- **Safari**: 14+
- **Mobile**: iOS 14+, Android Chrome 90+
**Required Features**:
- ES2020 JavaScript
- Promise support
- Async/await support
---
**Next**: [Error Tracking Module](error-tracking.md) →

View File

@@ -0,0 +1,140 @@
# Admin Auth Security Enhancement Plan
**Status**: Geplant für später (nach Refactoring anderer Module)
**Ansatz**: Starke Web-Authentifizierung ohne VPN
## Überblick
Erweitert das Auth-Modul für den Admin-Bereich mit mehrschichtiger Web-Authentifizierung. Fokus auf starke Authentifizierung mit MFA, Session-Sicherheit und Rate Limiting.
## Sicherheitsebenen
1. **Obligatorisches MFA (TOTP)** - Zweiter Faktor zwingend erforderlich
2. **Strenge Session-Sicherheit** - Regeneration, IP-Tracking, Timeouts
3. **Rate Limiting & Account Lockout** - Schutz gegen Brute-Force
4. **IP-basierte Einschränkungen** (optional) - Zusätzliche Barriere ohne VPN
5. **Security Headers** - CSRF-Schutz, Secure Cookies, HSTS
## Aktuelle Situation
- Basis-Authentifizierung mit Session-Management vorhanden
- MFA/TOTP-Services existieren (`TotpService`, `MfaService`), aber nicht vollständig integriert
- IP-basierte Einschränkungen existieren (`ProductionSecurityMiddleware`)
- AuthMiddleware ist derzeit deaktiviert
- RouteAuthorizationService existiert, aber nicht konfiguriert
## Implementation Plan
### Phase 1: Auth-Modul Erweiterung
1. **AdminAuthService** erstellen
- Integration mit bestehendem `AuthenticationService`
- Admin-spezifische Authentifizierungslogik
- Session-Management für Admin-Bereich
- IP-Tracking und Session-Regeneration
- MFA-Status-Prüfung
2. **MFA-Integration** für Admin-Bereich
- TOTP als obligatorische zweite Faktor über `MfaService`/`TotpProvider`
- QR-Code-Generierung für Setup
- Backup-Codes für Recovery
- MFA-Enforcement für alle Admin-Routen
3. **Session-Sicherheit** verbessern
- Session-Regeneration bei Login
- IP-Konsistenz-Prüfung (warnen bei IP-Wechsel)
- Session-Timeouts für Admin-Bereich (kürzer als normale Sessions)
- Session-Fixation-Schutz
- Secure Cookie-Flags (HttpOnly, Secure, SameSite)
### Phase 2: Route Protection & Authorization
1. **RouteAuthorizationService** aktivieren und konfigurieren
- Admin-Namespace (`App\Application\Admin\*`) konfigurieren
- IP-basierte Zugriffskontrolle (optional, aber empfohlen)
- MFA-Status-Prüfung für alle Admin-Routen
2. **AuthMiddleware** implementieren
- Integration mit `RouteAuthorizationService`
- Session-Validierung
- MFA-Status-Prüfung
- Redirect zu Login bei fehlender Authentifizierung
- Redirect zu MFA-Setup bei fehlender MFA-Konfiguration
3. **AdminLoginController** erstellen
- Login-Formular
- MFA-Setup-Flow (wenn noch nicht konfiguriert)
- MFA-Verifizierung nach initialem Login
- Session-Erstellung
- Logout-Funktionalität
### Phase 3: Erweiterte Sicherheitsfeatures
1. **IP-basierte Einschränkungen** (Optional, aber empfohlen)
- Statische IP-Whitelist für Admin-Zugriff
- CIDR-Notation für IP-Ranges unterstützen
- Konfigurierbar über Environment-Variablen
- Integration mit `ProductionSecurityMiddleware`
2. **Rate Limiting** für Admin-Bereich
- Striktere Limits als für normale User
- IP-basierte Rate Limits
- Account-Lockout nach fehlgeschlagenen Versuchen
- Separate Limits für Login, MFA-Verifizierung
3. **Security Headers**
- CSRF-Schutz für alle Admin-Formulare
- Secure Cookies (HTTPS-only)
- HSTS für Admin-Bereich
- Content-Security-Policy
## Dateien die erstellt/geändert werden müssen
### Neue Dateien
- `src/Framework/Auth/AdminAuthService.php` - Admin-spezifischer Auth-Service
- `src/Application/Admin/Auth/AdminLoginController.php` - Login-Controller
- `src/Framework/Auth/MfaRequiredException.php` - Exception für fehlende MFA
- `src/Framework/Auth/AdminMfaService.php` - MFA-Service für Admin-Bereich
- `src/Framework/Auth/AdminMfaSetupResult.php` - Result Value Objects
- `src/Framework/Auth/AdminMfaActivationResult.php`
- `src/Framework/Auth/AdminMfaVerificationResult.php`
- `tests/Framework/Auth/AdminAuthServiceTest.php` - Tests
- `tests/Framework/Auth/AdminMfaServiceTest.php` - MFA-Tests
### Zu erweiternde Dateien
- `src/Framework/Http/Middlewares/AuthMiddleware.php` - Vollständige Implementierung
- `src/Framework/Auth/RouteAuthorizationServiceInitializer.php` - Konfiguration aktivieren
- `src/Framework/Auth/AuthenticationService.php` - MFA-Integration
- `src/Framework/Http/Middlewares/ProductionSecurityMiddleware.php` - IP-Whitelist-Erweiterung
- `src/Framework/Config/EnvKey.php` - Environment-Keys hinzufügen
## Konfiguration
### Environment-Variablen
- `ADMIN_MFA_REQUIRED=true` - MFA obligatorisch
- `ADMIN_SESSION_TIMEOUT=1800` - Session-Timeout (30 Min)
- `ADMIN_IP_WHITELIST` - Optionale IP-Whitelist (komma-separiert, CIDR unterstützt)
- `ADMIN_RATE_LIMIT_ATTEMPTS=3` - Strikte Rate Limits
- `ADMIN_ACCOUNT_LOCKOUT_DURATION=3600` - Lockout nach Fehlversuchen (1h)
- `ADMIN_SESSION_REGENERATE_ON_LOGIN=true` - Session-Regeneration
- `ADMIN_CHECK_IP_CONSISTENCY=true` - IP-Wechsel überwachen
### MFA-Integration
- Verwende `MfaService` mit `TotpProvider` (nicht direkt `TotpService`)
- `MfaMethod::TOTP` für TOTP-Authentifizierung
- `MfaSecret`, `MfaChallenge`, `MfaCode` Value Objects verwenden
## Wichtige Hinweise
- **Kein VPN**: Lösung basiert auf starker Web-Authentifizierung ohne VPN
- **MFA obligatorisch**: Alle Admin-Routen erfordern konfigurierte und verifizierte MFA
- **Audit-Logging**: Wird später implementiert, wenn eine vollständige Audit-Lösung im Framework vorhanden ist
- **IP-Whitelist**: Optional, aber empfohlen für Production
## Referenzen
- MFA-Modul: `src/Framework/Mfa/`
- TotpProvider: `src/Framework/Mfa/Providers/TotpProvider.php`
- RouteAuthorizationService: `src/Framework/Auth/RouteAuthorizationService.php`
- ProductionSecurityMiddleware: `src/Framework/Http/Middlewares/ProductionSecurityMiddleware.php`

View File

@@ -0,0 +1,186 @@
# Root Directory Cleanup Plan
## 1. Files to Move
### Debug Scripts → scripts/debug/
```bash
mv debug_*.php scripts/debug/
mv test_*.php scripts/test/
mv simple_debug_tui.php scripts/debug/
mv populate_images_from_filesystem.php scripts/maintenance/
mv websocket.php scripts/test/
```
### Documentation → docs/
```bash
# Root markdown files to consolidate
mv AUTOLOADER_WORKAROUND.md docs/troubleshooting/
mv DEPLOYMENT*.md docs/deployment/
mv SSL-PRODUCTION-SETUP.md docs/deployment/
mv PRODUCTION-SECURITY-UPDATES.md docs/deployment/
mv README-*.md docs/guides/
mv TODO.md docs/
mv docs-*.md docs/planning/
```
### Public Directory Security Cleanup
```bash
# REMOVE from public/ (move to scripts/debug/)
mv public/debug.php scripts/debug/
mv public/test.php scripts/test/
mv public/security-test.php scripts/debug/
mv public/production-test.php scripts/debug/
mv public/quick-fix.php scripts/debug/
mv public/build-container.php scripts/debug/
mv public/force-production-test.php scripts/debug/
mv public/dev-hot-reload*.php scripts/debug/
mv public/minimal.php scripts/debug/
# public/ should only contain:
# - index.php (production entry point)
# - health.php (monitoring)
# - .vite/ (build artifacts)
# - assets/ (compiled assets)
```
## 2. New Directory Structure
```
michaelschiemer/
├── bin/ # Executable scripts
│ ├── console # Symlink to console.php
│ └── worker # Symlink to worker.php
├── config/ # Configuration files
│ └── static-routes.json
├── docs/ # Consolidated documentation
│ ├── README.md
│ ├── architecture/
│ │ ├── framework-principles.md
│ │ ├── di-container.md
│ │ └── discovery-system.md
│ ├── deployment/
│ │ ├── production-setup.md
│ │ ├── ssl-configuration.md
│ │ └── docker-guide.md
│ ├── guides/
│ │ ├── getting-started.md
│ │ ├── api-versioning.md
│ │ └── testing.md
│ ├── troubleshooting/
│ │ ├── autoloader-workaround.md
│ │ └── common-issues.md
│ └── planning/
│ └── TODO.md
├── public/ # Web-accessible (MINIMAL!)
│ ├── index.php
│ ├── health.php
│ └── .vite/
├── resources/ # Source assets
│ ├── css/
│ └── js/
├── scripts/ # Development & maintenance
│ ├── debug/ # Debug scripts (NOT web-accessible)
│ ├── test/ # Test scripts
│ ├── deployment/ # Deployment scripts
│ └── maintenance/ # Maintenance scripts
├── src/ # Application source
├── storage/ # Runtime data
│ ├── cache/ # Add to .gitignore
│ ├── logs/
│ └── uploads/
├── tests/ # Test suite
├── vendor/ # Composer dependencies
└── var/ # Temporary files
└── phpstan/cache/ # Add to .gitignore
```
## 3. Gitignore Updates
Add to `.gitignore`:
```
# Cache
storage/cache/*.cache.php
storage/cache/*.php
# PHPStan
var/phpstan/cache/**
# Logs
storage/logs/*.log
# Temporary debug files
scripts/debug/output/
scripts/test/output/
```
## 4. Immediate Actions
### Priority 1: Security (DO IMMEDIATELY!)
```bash
# Remove debug files from public/
rm public/debug.php
rm public/test.php
rm public/security-test.php
rm public/production-test.php
rm public/quick-fix.php
rm public/build-container.php
rm public/force-production-test.php
rm public/dev-hot-reload.php
rm public/dev-hot-reload-minimal.php
rm public/minimal.php
```
### Priority 2: Cache Cleanup
```bash
# Clear old cache files
find storage/cache -name "*.cache.php" -mtime +7 -delete
find var/phpstan/cache -type f -mtime +7 -delete
```
### Priority 3: Documentation Consolidation
```bash
# Create new structure
mkdir -p docs/{architecture,deployment,guides,troubleshooting,planning}
mkdir -p scripts/{debug,test,deployment,maintenance}
# Move files (execute moves from section 1)
```
## 5. Benefits
-**Security**: No debug code in public/
-**Organization**: Clear separation of concerns
-**Performance**: Cleaner cache structure
-**Developer Experience**: Easy navigation
-**Professional**: Clean root directory
-**Maintainability**: Consolidated documentation
## 6. Automated Cleanup Script
Create `scripts/maintenance/cleanup-project.php`:
```php
#!/usr/bin/env php
<?php
// Automated cleanup script
// - Clear old cache files
// - Remove temporary files
// - Validate directory structure
```
## Execution Timeline
**Week 1**:
- Security cleanup (public/ directory)
- Cache cleanup
**Week 2**:
- Documentation consolidation
- Root directory organization
**Week 3**:
- Script organization
- Automated cleanup tools
**Week 4**:
- Validation & testing
- Update documentation

View File

@@ -0,0 +1,160 @@
# 🧪 LiveComponents Test Guide
## Quick Test
1. **Start Server**:
```bash
make up
npm run dev
```
2. **Open Test Page**:
```
https://localhost/test/livecomponents
```
3. **Test Counter Component**:
- ✅ Click **+ Increment** → Count increases
- ✅ Click **- Decrement** → Count decreases
- ✅ Click **Reset** → Count resets to 0
- ✅ Enter **5** and click **Add Amount** → Count +5
- ✅ Wait 10 seconds → Auto-update (polling)
## What's Being Tested
### ✅ Core Features
- **Action Handling** - Button clicks execute component methods
- **Form Submission** - Forms with parameters work
- **State Management** - Component data persists and updates
- **Polling** - Auto-updates every 10 seconds
- **DOM Updates** - HTML re-renders on state change
### ✅ Framework Patterns
- **Trait + Interface** - No abstract classes
- **Readonly Classes** - Immutable components
- **Value Objects** - Type-safe data handling
- **Dependency Injection** - TemplateRenderer injection
### ✅ JavaScript
- **Zero Dependencies** - Pure Vanilla JS
- **Auto-initialization** - Finds components on page load
- **Event Handling** - Buttons, forms, polling
- **Progress Tracking** - Upload progress (ready for file uploads)
## Test Files
```
src/
├── Application/
│ ├── Controllers/Test/
│ │ ├── LiveComponentTestController.php ← Test Route
│ │ └── README.md ← Test Documentation
│ └── Components/
│ └── CounterComponent.php ← Test Component
├── Framework/LiveComponents/
│ └── Templates/
│ └── counter.view.php ← Component Template
└── resources/views/test/
└── livecomponents.view.php ← Test Page
```
## Browser Console Output
Expected console output:
```javascript
LiveComponents Test Suite Loaded
Available: {
liveComponents: LiveComponentManager,
sseManager: SSEManager
}
```
## Network Requests
Watch for:
```
POST /live-component/App\Application\Components\CounterComponent:demo
Request:
{
"component_id": "App\\Application\\Components\\CounterComponent:demo",
"method": "increment",
"params": {},
"state": { "count": 0 }
}
Response:
{
"html": "<div>...</div>",
"events": [],
"state": "{\"id\":\"...\",\"component\":\"...\",\"data\":{\"count\":1}}"
}
```
## Debugging
### ❌ Component not initializing?
```javascript
// Check if LiveComponents loaded
console.log(window.liveComponents);
// Check component registered
console.log(window.liveComponents.components);
```
### ❌ Actions not working?
```javascript
// Manual action call
window.liveComponents.callAction(
'App\\Application\\Components\\CounterComponent:demo',
'increment',
{}
);
```
### ❌ Polling not working?
```javascript
// Check polling interval
document.querySelector('[data-poll-interval]').dataset.pollInterval;
// Force poll
window.liveComponents.callAction('CounterComponent:demo', 'poll', {});
```
## Next: Add Your Own Component
```php
// 1. Create Component
final readonly class MyComponent implements LiveComponentContract
{
use LiveComponentTrait;
public function __construct(string $id, array $initialData = [], ?TemplateRenderer $templateRenderer = null) {
$this->id = $id;
$this->initialData = $initialData;
$this->templateRenderer = $templateRenderer;
}
public function render(): string {
return $this->template('Framework/LiveComponents/Templates/my-component', []);
}
public function myAction(): array {
return ['updated' => true];
}
}
// 2. Add to LiveComponentTestController
$myComponent = new MyComponent(
id: ComponentRegistry::makeId(MyComponent::class, 'test')
);
// 3. Render in view
{!! myComponent.toHtml() !!}
```
## Documentation
- 📚 Full docs: `/docs/claude/livecomponents-system.md`
- 📦 Module README: `/src/Framework/LiveComponents/README.md`
- 🧪 Test README: `/src/Application/Controllers/Test/README.md`

View File

@@ -0,0 +1,368 @@
# Src Directory Structure Improvements
## Current Issues
### 1. Application Layer Fragmentation
```
src/Application/
├── Admin/ # Admin features
├── Api/ # API endpoints
├── Auth/ # Authentication
├── Backend/ # Backend integrations?
├── Campaign/ # Campaign management
├── Controller/ # Generic controllers?
├── Design/ # Design system?
├── Http/ # HTTP utilities
├── Service/ # Generic services?
├── Website/ # Website pages
└── ... (20+ directories)
```
**Problem**:
- No clear separation between features and infrastructure
- Mix of feature modules and technical layers
- Hard to find related code
### 2. Framework Layer Organization
```
src/Framework/
├── Async/
├── AsyncExamples/ # Examples should not be in Framework/
├── Cache/
├── Database/
├── DI/
├── Discovery/
└── ... (50+ directories)
```
**Problem**:
- Examples mixed with production code
- Very deep nesting (Database/Schema/Index/Analysis/)
- Some modules could be consolidated
### 3. Domain Layer Inconsistency
```
src/Domain/
├── AI/ # Is this really domain?
├── Common/ # Shared code
├── Contact/
├── Media/
├── Meta/ # What is Meta domain?
├── Newsletter/
├── PreSave/ # Feature-specific
├── SmartLink/
└── User/
```
**Problem**:
- Mix of bounded contexts and shared code
- Unclear domain boundaries
- Technical concerns (AI) mixed with business domains
## Proposed Improvements
### A. Application Layer Restructuring
**Option 1: Feature-Based Modules** (RECOMMENDED)
```
src/Application/
├── Admin/ # Admin Panel Feature
│ ├── Analytics/
│ ├── Content/
│ ├── System/
│ └── Controllers/
├── Api/ # API Layer
│ ├── V1/
│ ├── V2/
│ └── Middleware/
├── Auth/ # Authentication Feature
│ ├── Controllers/
│ ├── Middleware/
│ └── Services/
├── Campaign/ # Campaign Management Feature
│ ├── Controllers/
│ ├── Services/
│ └── ValueObjects/
├── Website/ # Public Website Feature
│ ├── Controllers/
│ ├── Services/
│ └── templates/
└── Shared/ # Application-wide shared code
├── Controllers/ # Base controllers
├── Middleware/
└── Services/
```
**Benefits**:
- Clear feature boundaries
- Related code grouped together
- Easy to find and navigate
- Follows Vertical Slice Architecture
**Option 2: Layer-Based Organization**
```
src/Application/
├── Controllers/ # All controllers
│ ├── Admin/
│ ├── Api/
│ ├── Auth/
│ └── Website/
├── Services/ # All services
├── Middleware/ # All middleware
└── ValueObjects/ # Application VOs
```
**Benefits**:
- Technical separation
- Easy to see all controllers/services
- Simpler structure
**Downside**: Harder to see complete features
### B. Framework Layer Improvements
**Clean Up Examples**:
```bash
# Move examples OUT of src/Framework/
src/
├── Framework/ # Production framework code
│ ├── Cache/
│ ├── Database/
│ ├── DI/
│ └── ...
└── Examples/ # All examples here
├── Async/
├── Cache/
├── Database/
└── GraphQL/
```
**Consolidate Deep Nesting**:
```
src/Framework/Database/
├── Connection/ # Consolidated connection handling
│ ├── Async/
│ ├── Middleware/
│ ├── Pooled/
│ └── ReadWrite/
├── Migration/
│ ├── Commands/
│ ├── Runners/
│ └── ValueObjects/
├── Monitoring/
│ ├── Health/
│ ├── Profiling/
│ └── Metrics/
├── QueryBuilder/
├── Repository/
├── Schema/
│ ├── Blueprint/
│ ├── Comparison/
│ └── Index/
└── UnitOfWork/
```
**Instead of**:
```
Database/
Monitoring/
Health/
Checks/ # Too deep!
```
### C. Domain Layer Restructuring
**Bounded Contexts Approach**:
```
src/Domain/
├── BoundedContexts/ # Clear business domains
│ ├── Campaign/
│ │ ├── Entities/
│ │ ├── ValueObjects/
│ │ ├── Services/
│ │ └── Repositories/
│ ├── Contact/
│ ├── Media/
│ ├── Newsletter/
│ ├── SmartLink/ # Renamed from PreSave
│ └── User/
├── Shared/ # Shared Kernel
│ ├── ValueObjects/ # Cross-domain VOs
│ ├── Interfaces/
│ └── Exceptions/
└── Services/ # Domain Services
└── AI/ # AI as domain service
```
**Benefits**:
- Clear bounded context boundaries
- Shared kernel explicit
- Domain services separated
- DDD-compliant structure
## Migration Strategy
### Phase 1: Immediate Cleanup (Week 1)
```bash
# 1. Move examples out of Framework
mkdir -p examples
mv src/Framework/AsyncExamples examples/Async
mv src/Framework/Database/Examples examples/Database
# ... repeat for all examples
# 2. Update composer.json autoload
"autoload": {
"psr-4": {
"App\\": "src/",
"Examples\\": "examples/"
}
}
# 3. Regenerate autoloader
composer dump-autoload
```
### Phase 2: Documentation (Week 2)
```bash
# Create architecture docs
docs/architecture/
├── application-layer.md # Feature-based organization
├── framework-layer.md # Framework structure
├── domain-layer.md # Bounded contexts
└── migration-guide.md # How to navigate new structure
```
### Phase 3: Gradual Migration (Weeks 3-6)
- Move Application code to feature modules (one at a time)
- Consolidate Framework deep nesting
- Restructure Domain bounded contexts
- Update imports and tests
## Recommended Final Structure
```
michaelschiemer/
├── bin/
├── config/
├── docs/
│ ├── architecture/
│ ├── deployment/
│ └── guides/
├── examples/ # All framework examples
│ ├── Async/
│ ├── Cache/
│ ├── Database/
│ └── GraphQL/
├── public/ # Minimal! Only index.php + health.php
├── resources/
│ ├── css/
│ └── js/
├── scripts/
│ ├── debug/
│ ├── test/
│ ├── deployment/
│ └── maintenance/
├── src/
│ ├── Application/ # Feature-based modules
│ │ ├── Admin/
│ │ ├── Api/
│ │ ├── Auth/
│ │ ├── Campaign/
│ │ ├── Website/
│ │ └── Shared/
│ ├── Domain/ # Bounded contexts
│ │ ├── BoundedContexts/
│ │ │ ├── Campaign/
│ │ │ ├── Contact/
│ │ │ ├── Media/
│ │ │ ├── Newsletter/
│ │ │ ├── SmartLink/
│ │ │ └── User/
│ │ ├── Shared/
│ │ └── Services/
│ ├── Framework/ # Framework (production only)
│ │ ├── Cache/
│ │ ├── Console/
│ │ ├── Database/
│ │ ├── DI/
│ │ ├── Discovery/
│ │ ├── Http/
│ │ └── ...
│ └── Infrastructure/ # External integrations
│ ├── GeoIp/
│ └── ...
├── storage/
├── tests/ # Mirrors src/ structure
│ ├── Application/
│ ├── Domain/
│ ├── Framework/
│ └── Integration/
├── var/
└── vendor/
```
## Quality Metrics
**Before**:
- Root files: 105
- Public debug files: 9
- Application directories: 25+
- Framework nesting depth: 6 levels
- Examples in production: Yes
**After**:
- Root files: ~15 (essential only)
- Public debug files: 0 (SECURITY!)
- Application modules: ~8 (feature-based)
- Framework nesting depth: 3-4 levels max
- Examples location: Separate examples/ directory
## Implementation Checklist
- [ ] Move debug/test scripts to scripts/
- [ ] Clean up public/ directory (SECURITY PRIORITY!)
- [ ] Move examples out of src/Framework/
- [ ] Create examples/ directory
- [ ] Consolidate documentation in docs/
- [ ] Restructure Application layer (feature-based)
- [ ] Simplify Framework deep nesting
- [ ] Organize Domain bounded contexts
- [ ] Update composer autoload
- [ ] Update all imports
- [ ] Update tests to match new structure
- [ ] Update .gitignore
- [ ] Clear old cache files
- [ ] Document new structure
- [ ] Create navigation guide
## Tools to Create
### 1. Structure Validator
```bash
php console.php structure:validate
# Checks:
# - No PHP files in public/ except index.php/health.php
# - All examples in examples/ directory
# - Cache size warnings
# - Proper namespace structure
```
### 2. Automatic Cleanup
```bash
php console.php cleanup:project
# Actions:
# - Clear old cache files
# - Remove temporary files
# - Report orphaned files
```
### 3. Migration Helper
```bash
php console.php migrate:structure --dry-run
# Shows what would be moved/changed
# Then run without --dry-run to execute
```

View File

@@ -0,0 +1,112 @@
# Code Quality Scanner
This module provides repository-aware rules that validate architectural conventions. It currently ships with the following rules:
- `StringableImplementation`: classes that define `__toString()` must implement `Stringable`
- `FinalClass`: value-object classes must be declared `final`
- `ReadonlyClass`: value-object classes must be declared `readonly`
- `ReadonlyGetter`: readonly properties (or classes) should be exposed directly; avoid `get*()` wrappers
- `NoInheritance`: inheritance is forbidden (except for a small allow list, e.g. Exceptions)
## Command Line Usage
Run the scanner from the project root:
```bash
php console.php quality:scan # scans src/ by default
php console.php quality:scan app/path # scan a custom directory
php console.php quality:scan --skip-errors # skip classes/files that cannot be parsed
```
The command groups violations by rule and shows file locations:
```
❌ Found 2 violation(s). Scanned 185 files, 174 classes in 6.91s
StringableImplementation (2)
• App\Domain\User\ValueObjects\UserId
↳ src/Domain/User/ValueObjects/UserId.php:42
Classes defining __toString() must implement Stringable explicitly.
```
The exit code is `0` when all checks pass, or `1` when violations are found. You can wire this command into CI to block regressions.
### Skipping Faulty Classes
Some parts of the repository (legacy examples, experimental prototypes, etc.) may not load because they contain invalid PHP constructs or depend on unavailable interfaces. Use the `--skip-errors` flag to collect a warning and continue scanning the remaining classes:
```bash
php console.php quality:scan --skip-errors
```
When the flag is omitted, any parsing/reflection error stops the scan and the command exits with a non-zero status.
## Adding New Rules
Rules implement `App\Framework\Quality\CodeQuality\CodeQualityRule`:
```php
use App\Framework\Quality\CodeQuality\CodeQualityRule;
use App\Framework\Quality\CodeQuality\Results\RuleViolation;
use App\Framework\Quality\CodeQuality\ValueObjects\ClassInspection;
final class MyCustomRule implements CodeQualityRule
{
public function name(): string
{
return 'MyCustomRule';
}
public function check(ClassInspection $inspection): array
{
if ($this->isValid($inspection)) {
return [];
}
$line = $inspection->getMethodLine('someMethod');
return [
RuleViolation::create(
$inspection->className(),
$inspection->filePath(),
$this->name(),
'Explain what must change.',
$line
),
];
}
}
```
Register the rule inside `CodeQualityScanCommand`:
```php
$this->scanner = new CodeQualityScanner(
$fileScanner,
$reflectionService,
[
new RequireStringableImplementationRule(),
new MyCustomRule(),
],
$logger
);
```
Because rules leverage full reflection data and the actual file path, you have the flexibility to enforce namespacing, attribute usage, dependency boundaries, and more.
## Storage Permissions
The scanner runs inside the console bootstrap. When Redis is unavailable, the framework falls back to the filesystem cache. The cache directory now resolves to `<project-root>/storage/cache`, but you still need to make sure it exists and is writable:
```bash
mkdir -p storage/cache
chmod -R ug+rw storage
```
If you run the command from another working directory (e.g. inside Docker), set the base path explicitly so the cache resolver finds the right storage folder:
```bash
APP_BASE_PATH=/home/michael/dev/michaelschiemer php console.php quality:scan
```
The CLI entry point already exports `APP_BASE_PATH`; keep the environment variable handy for custom runners, background workers, or integration tests.

View File

@@ -0,0 +1,318 @@
# Design Token System - Empfohlene Features
## Übersicht
Dieses Dokument beschreibt empfohlene Erweiterungen für das Design Token System, die das System noch mächtiger und flexibler machen würden.
## Phase 1: Datenbank-Speicherung (Priorität: Hoch)
### 1.1 Database Schema
- **Datei**: `src/Framework/Design/Migrations/CreateDesignTokensTable.php`
- **Schema**:
- `id` (VARCHAR 255, Primary Key)
- `name` (VARCHAR 255, NOT NULL)
- `type` (VARCHAR 50) - 'color', 'spacing', 'typography', etc.
- `state` (VARCHAR 50, DEFAULT 'default')
- `scope` (VARCHAR 100) - 'framework', 'admin', etc.
- `value_data` (JSON) - Token-Wert
- `base_token_id` (VARCHAR 255, NULL) - Für abgeleitete Tokens
- `mutation_data` (JSON, NULL) - StateMutation als JSON
- `description` (TEXT)
- `metadata` (JSON)
- `created_at`, `updated_at` (TIMESTAMP)
- Indizes: `(name, state, scope)`, `scope`, `type`, `state`
### 1.2 DesignTokenEntity
- **Datei**: `src/Framework/Design/Database/DesignTokenEntity.php`
- **Funktionalität**: Entity-Mapping für Design Tokens
- **Features**:
- Serialisierung/Deserialisierung von Token-ValueObjects
- StateMutation als JSON speichern/laden
- Versionierung von Tokens
### 1.3 DatabaseTokenRepository
- **Datei**: `src/Framework/Design/Repositories/DatabaseTokenRepository.php`
- **Funktionalität**:
- Lädt Tokens aus Datenbank
- Konvertiert DB-Entities zu TokenInterface
- Caching für Performance
- Filterung nach Scope, Type, State
### 1.4 HybridTokenRegistry
- **Datei**: `src/Framework/Design/ValueObjects/HybridTokenRegistry.php`
- **Funktionalität**:
- Lädt Code-basierte Tokens (wie bisher)
- Lädt DB-Tokens (optional)
- Merged beide Quellen (DB überschreibt Code)
- Cache für Performance
- Hot-Reload für DB-Änderungen (optional)
**Vorteile**:
- Dynamische Anpassung ohne Code-Deployment
- UI für Token-Verwaltung möglich
- Versionierung/Audit-Trail
- Multi-Tenant Support
## Phase 2: Token-Validierung & Linting (Priorität: Mittel)
### 2.1 Token Validator
- **Datei**: `src/Framework/Design/Validators/TokenValidator.php`
- **Funktionalität**:
- Validiert Token-Werte (z.B. OKLCH-Werte im gültigen Bereich)
- Prüft auf fehlende States
- Prüft auf inkonsistente Mutationen
- WCAG-Kontrast-Validierung für Farben
### 2.2 Token Linter
- **Datei**: `src/Framework/Design/Linters/TokenLinter.php`
- **Funktionalität**:
- Prüft Naming Conventions
- Prüft auf ungenutzte Tokens
- Prüft auf fehlende Fallbacks
- Prüft auf Performance-Probleme
### 2.3 Console Command
- **Datei**: `src/Application/Console/Commands/Design/ValidateTokensCommand.php`
- **Command**: `design:validate-tokens`
- **Funktionalität**:
- Validiert alle Tokens
- Zeigt Linter-Warnungen
- Prüft WCAG-Kontrast
- Generiert Report
## Phase 3: Token-Export & Import (Priorität: Mittel)
### 3.1 Export-Formate
- **JSON**: Standard JSON-Format für Tokens
- **W3C Design Tokens**: W3C Design Tokens Format
- **Style Dictionary**: Style Dictionary Format
- **CSS Variables**: Reine CSS Custom Properties
- **TypeScript**: TypeScript-Typen für Frontend
### 3.2 Import-Formate
- **JSON**: Import aus JSON
- **W3C Design Tokens**: Import aus W3C Format
- **CSS**: Parse bestehende CSS Custom Properties
- **Figma Tokens**: Import aus Figma Tokens Plugin
### 3.3 Console Commands
- **Datei**: `src/Application/Console/Commands/Design/ExportTokensCommand.php`
- **Command**: `design:export-tokens --format=json|w3c|css|typescript`
- **Datei**: `src/Application/Console/Commands/Design/ImportTokensCommand.php`
- **Command**: `design:import-tokens --file=path/to/tokens.json --format=json`
## Phase 4: Token-Themes & Varianten (Priorität: Hoch)
### 4.1 Theme System
- **Datei**: `src/Framework/Design/ValueObjects/Theme.php`
- **Funktionalität**:
- Definiert Theme-Varianten (z.B. "Light", "Dark", "High Contrast")
- Theme-spezifische Token-Überschreibungen
- Theme-Wechsel zur Laufzeit
### 4.2 Theme Registry
- **Datei**: `src/Framework/Design/ValueObjects/ThemeRegistry.php`
- **Funktionalität**:
- Verwaltet mehrere Themes
- Theme-Aktivierung
- Theme-Merging (Basis-Theme + Varianten)
### 4.3 CSS-Generierung für Themes
- **Erweiterung**: `CssAstBuilder` generiert CSS für alle Themes
- **Output**: Separate CSS-Dateien oder CSS-Variablen mit Theme-Präfix
**Beispiel**:
```css
[data-theme="light"] {
--color-primary: oklch(70% 0.2 295);
}
[data-theme="dark"] {
--color-primary: oklch(60% 0.22 295);
}
[data-theme="high-contrast"] {
--color-primary: oklch(50% 0.3 295);
}
```
## Phase 5: Token-Dokumentation & Storybook-Integration (Priorität: Niedrig)
### 5.1 Automatische Dokumentation
- **Datei**: `src/Framework/Design/Documentation/TokenDocumentationGenerator.php`
- **Funktionalität**:
- Generiert Markdown-Dokumentation aus Tokens
- Zeigt alle Token-Werte
- Zeigt State-Variationen
- Zeigt Verwendungsbeispiele
### 5.2 Storybook Integration
- **Datei**: `src/Framework/Design/Storybook/TokenStoriesGenerator.php`
- **Funktionalität**:
- Generiert Storybook-Stories für Tokens
- Visualisiert Token-Werte
- Zeigt State-Variationen
- Interaktive Token-Exploration
### 5.3 Token-Showcase
- **Datei**: `src/Application/Admin/Controllers/DesignTokenShowcaseController.php`
- **Funktionalität**:
- Admin-UI für Token-Visualisierung
- Interaktive Token-Exploration
- State-Variationen anzeigen
- Export-Funktionen
## Phase 6: Token-Performance-Optimierung (Priorität: Mittel)
### 6.1 CSS-Optimierung
- **Minification**: Minimiert generiertes CSS
- **Tree-Shaking**: Entfernt ungenutzte Tokens
- **Critical CSS**: Extrahiert kritische Tokens
- **CSS-Layering**: Optimiert @layer-Struktur
### 6.2 Caching-Strategien
- **Token-Cache**: Cached geladene Tokens
- **CSS-Cache**: Cached generiertes CSS
- **Invalidation**: Intelligente Cache-Invalidierung
- **Preloading**: Preload häufig verwendeter Tokens
### 6.3 Lazy Loading
- **On-Demand Loading**: Lädt Tokens nur bei Bedarf
- **Code-Splitting**: Splittet Token-CSS nach Scope
- **Dynamic Imports**: Dynamische CSS-Imports
## Phase 7: Token-Testing & QA (Priorität: Mittel)
### 7.1 Unit Tests
- **Token-Tests**: Testet Token-Erstellung und -Manipulation
- **Mutation-Tests**: Testet State-Mutationen
- **CSS-Generierung-Tests**: Testet CSS-Output
### 7.2 Visual Regression Tests
- **Screenshot-Tests**: Vergleicht Token-Rendering
- **State-Variation-Tests**: Testet alle States
- **Theme-Tests**: Testet Theme-Varianten
### 7.3 Accessibility Tests
- **Kontrast-Tests**: Automatische WCAG-Kontrast-Prüfung
- **Color-Blindness-Tests**: Simuliert Farbenblindheit
- **Screen-Reader-Tests**: Prüft Screen-Reader-Kompatibilität
## Phase 8: Token-Editor UI (Priorität: Niedrig)
### 8.1 Admin-Interface
- **Token-Editor**: Visueller Editor für Tokens
- **Color-Picker**: OKLCH-basierter Color-Picker
- **State-Editor**: Editor für State-Mutationen
- **Live-Preview**: Live-Vorschau der Änderungen
### 8.2 Token-Management
- **CRUD-Operationen**: Create, Read, Update, Delete für Tokens
- **Bulk-Operations**: Massenbearbeitung von Tokens
- **Import/Export**: UI für Import/Export
- **Versionierung**: UI für Token-Versionen
### 8.3 Analytics
- **Token-Usage**: Zeigt Verwendung von Tokens
- **Performance-Metriken**: Zeigt Performance-Impact
- **Accessibility-Scores**: Zeigt Accessibility-Scores
## Phase 9: Erweiterte Farb-Features (Priorität: Niedrig)
### 9.1 Farb-Paletten-Generierung
- **Datei**: `src/Framework/Design/Services/ColorPaletteGenerator.php`
- **Funktionalität**:
- Generiert Farb-Paletten aus Basis-Farbe
- Harmonische Farb-Kombinationen
- Kontrast-optimierte Paletten
- Accessibility-optimierte Paletten
### 9.2 Farb-Analyse
- **Datei**: `src/Framework/Design/Services/ColorAnalyzer.php`
- **Funktionalität**:
- Analysiert Farb-Eigenschaften
- Berechnet Kontrast-Verhältnisse
- Erkennt Farb-Harmonien
- Simuliert Farbenblindheit
### 9.3 Farb-Konvertierung
- **Erweiterung**: Unterstützung für weitere Farb-Räume
- LAB, LUV, XYZ
- CMYK
- Pantone (näherungsweise)
- NCS (Natural Color System)
## Phase 10: Token-Versionierung & Migration (Priorität: Mittel)
### 10.1 Token-Versionierung
- **Datei**: `src/Framework/Design/ValueObjects/TokenVersion.php`
- **Funktionalität**:
- Versions-Tracking für Tokens
- Semantische Versionierung
- Changelog-Generierung
- Breaking Changes Detection
### 10.2 Migration-Tools
- **Datei**: `src/Framework/Design/Migrations/TokenMigration.php`
- **Funktionalität**:
- Automatische Token-Migrationen
- Bulk-Updates
- Deprecation-Warnings
- Auto-Fix für einfache Änderungen
### 10.3 Rollback-Mechanismus
- **Funktionalität**:
- Rollback zu vorherigen Token-Versionen
- Version-Vergleich
- Diff-Visualisierung
## Priorisierung
### Kurzfristig (1-2 Monate)
1. **Datenbank-Speicherung** (Phase 1) - Ermöglicht dynamische Token-Verwaltung
2. **Token-Themes** (Phase 4) - Wichtiges Feature für Multi-Theme-Support
3. **Token-Validierung** (Phase 2) - Qualitätssicherung
### Mittelfristig (3-6 Monate)
4. **Token-Export/Import** (Phase 3) - Integration mit Design-Tools
5. **Performance-Optimierung** (Phase 6) - Skalierbarkeit
6. **Token-Testing** (Phase 7) - Qualitätssicherung
### Langfristig (6+ Monate)
7. **Token-Dokumentation** (Phase 5) - Developer Experience
8. **Token-Editor UI** (Phase 8) - Benutzerfreundlichkeit
9. **Erweiterte Farb-Features** (Phase 9) - Erweiterte Funktionalität
10. **Token-Versionierung** (Phase 10) - Enterprise-Features
## Abhängigkeiten
- **Phase 1** (Datenbank) ist Voraussetzung für **Phase 8** (Editor UI)
- **Phase 2** (Validierung) ist Voraussetzung für **Phase 10** (Versionierung)
- **Phase 4** (Themes) kann parallel zu anderen Phasen entwickelt werden
- **Phase 6** (Performance) profitiert von allen vorherigen Phasen
## Technische Überlegungen
### Datenbank-Speicherung
- **Hybrid-Ansatz**: Code-basierte Tokens als Default, DB als Override
- **Caching**: Aggressives Caching für Performance
- **Migration**: Schrittweise Migration von Code zu DB
### Performance
- **Lazy Loading**: Tokens nur bei Bedarf laden
- **CSS-Optimierung**: Minimierung und Tree-Shaking
- **CDN-Integration**: Generiertes CSS auf CDN ausliefern
### Skalierbarkeit
- **Multi-Tenant**: Unterstützung für mehrere Tenant-Token-Sets
- **Caching-Strategien**: Verschiedene Caching-Ebenen
- **Load Balancing**: Verteilung der Token-Generierung
## Erfolgs-Metriken
- **Developer Experience**: Reduzierte Zeit für Token-Verwaltung
- **Performance**: Schnellere CSS-Generierung
- **Qualität**: Weniger Token-Fehler durch Validierung
- **Flexibilität**: Einfacheres Theme-Management
- **Integration**: Bessere Integration mit Design-Tools

585
docs/todo/todo.md Normal file
View File

@@ -0,0 +1,585 @@
# Console Template System & ConsoleResponse - Implementation Plan
## 📋 Übersicht
Implementierung eines Template-Systems für Console-Ausgaben mit `ConsoleResponse` Value Objects, das nahtlos mit dem bestehenden attribute-basierten Command-System arbeitet.
---
## 🎯 Phase 1: ConsoleResponse Foundation (Woche 1)
### 1.1 Core Interfaces & Base Classes
**Ziel**: Framework-compliant Response-Architektur
**Tasks**:
- [ ] `ConsoleResponse` Interface erstellen
- `getExitCode(): ExitCode`
- `render(ConsoleOutputInterface $output): void`
- `getData(): array`
- [ ] `AbstractConsoleResponse` Base Class
- Readonly class mit gemeinsamer Logik
- Constructor mit ExitCode und Data
- Gemeinsame Methoden-Implementierung
**Files**:
- `src/Framework/Console/Response/ConsoleResponse.php`
- `src/Framework/Console/Response/AbstractConsoleResponse.php`
### 1.2 Response Type Implementations
**Ziel**: 6 konkrete Response-Typen für verschiedene Use Cases
**Tasks**:
- [ ] `ConsoleTextResponse` - Simple Text-Ausgabe
- Factory Methods: `success()`, `error()`, `warning()`, `info()`
- Support für ConsoleStyle
- Readonly Value Object
- [ ] `ConsoleTableResponse` - Table-basierte Ausgabe
- Wiederverwendung der bestehenden `Table` Klasse
- Optional: Title Support
- Headers und Rows als Constructor-Parameter
- [ ] `ConsoleTemplateResponse` - Template-basierte Ausgabe
- Template Name + Data
- Integration mit ConsoleTemplateEngine (Phase 2)
- Lazy Loading von Template
- [ ] `ConsoleLayoutResponse` - Component-basierte Ausgabe
- ConsoleLayout als Parameter
- Wiederverwendung von Layout-System
- Multi-Component Rendering
- [ ] `ConsoleMenuResponse` - Interactive Menu
- Wiederverwendung von `InteractiveMenu`
- Items, Title, Interactive-Flag
- Selected Value in Data speichern
- [ ] `ConsoleCompositeResponse` - Mehrere Responses kombinieren
- Array von ConsoleResponse
- Sequential Rendering
- Exit Code Aggregation (schlechtester gewinnt)
**Files**:
- `src/Framework/Console/Response/ConsoleTextResponse.php`
- `src/Framework/Console/Response/ConsoleTableResponse.php`
- `src/Framework/Console/Response/ConsoleTemplateResponse.php`
- `src/Framework/Console/Response/ConsoleLayoutResponse.php`
- `src/Framework/Console/Response/ConsoleMenuResponse.php`
- `src/Framework/Console/Response/ConsoleCompositeResponse.php`
### 1.3 Response Builder (Fluent API)
**Ziel**: Einfache Erstellung komplexer Responses
**Tasks**:
- [ ] `ConsoleResponseBuilder` implementieren
- `addText(string, ?ConsoleStyle): self`
- `addTable(array, array, ?string): self`
- `addTemplate(string, array): self`
- `addDivider(): self`
- `addNewLine(int): self`
- `withExitCode(ExitCode): self`
- `withData(array): self`
- `build(): ConsoleResponse`
**Features**:
- Fluent Interface
- Auto-Composite wenn mehrere Sections
- Single Response wenn nur eine Section
**Files**:
- `src/Framework/Console/Response/ConsoleResponseBuilder.php`
### 1.4 Console Application Integration
**Ziel**: Support für ExitCode UND ConsoleResponse Return-Typen
**Tasks**:
- [ ] `ConsoleApplication` erweitern für beide Return-Typen
- Pattern Matching für `ExitCode|ConsoleResponse|int`
- `handleResponse(ConsoleResponse): int` Methode
- Backward Compatibility sicherstellen
- [ ] Method Signature Patterns dokumentieren
- Pattern A: `ConsoleResponse` only (Recommended)
- Pattern B: `ExitCode` only (Legacy)
- Pattern C: Both (Transition)
- Pattern D: Union Type (Flexible)
**Files**:
- `src/Framework/Console/ConsoleApplication.php` (Update)
### 1.5 Tests Phase 1
**Ziel**: ≥80% Test Coverage für Response-System
**Tasks**:
- [ ] Unit Tests für alle Response-Typen
- Constructor-Validierung
- Rendering-Logik
- Factory Methods
- getData() und getExitCode()
- [ ] Integration Tests
- ConsoleApplication mit verschiedenen Return-Typen
- ConsoleResponseBuilder Workflows
- Composite Response mit mehreren Sections
- [ ] Example Commands
- Beispiel für jede Response-Type
- Migration-Guide-Examples
**Files**:
- `tests/Unit/Console/Response/*Test.php`
- `tests/Feature/Console/ResponseIntegrationTest.php`
**Deliverables Phase 1**:
- ✅ ConsoleResponse Interface & 6 Typen
- ✅ ConsoleResponseBuilder Fluent API
- ✅ Backward-Compatible Console Application
- ✅ Comprehensive Test Suite
- ✅ Documentation & Examples
---
## 🎨 Phase 2: Console Template System (Woche 2)
### 2.1 String-Based Template Processors
**Ziel**: Template-Verarbeitung ähnlich wie HTML-Template-System
**Tasks**:
- [ ] `ConsoleTemplateProcessor` Interface
- `process(string $template, array $data): string`
- String-basiert (nicht DOM!)
- [ ] `ConsolePlaceholderProcessor`
- `{{ variable }}` - Escaped Output
- `{{{ raw }}}` - Raw Output (für ANSI codes)
- `{{ object.property }}` - Dot-Notation
- `{{ function() }}` - Function Calls
- Ähnlich wie `PlaceholderReplacer` aus View-System
- [ ] `ConsoleForProcessor`
- `<for items="..." as="...">` Syntax
- String-basiertes Loop-Processing
- Nested Loop Support
- Dot-Notation für Items-Path
- [ ] `ConsoleIfProcessor` (Optional)
- `<if condition="...">` Syntax
- Simple Conditional Logic
- `<else>` Support
**Files**:
- `src/Framework/Console/Template/ConsoleTemplateProcessor.php`
- `src/Framework/Console/Template/Processors/ConsolePlaceholderProcessor.php`
- `src/Framework/Console/Template/Processors/ConsoleForProcessor.php`
- `src/Framework/Console/Template/Processors/ConsoleIfProcessor.php`
### 2.2 Template Engine & Loader
**Ziel**: Unified Template Processing Pipeline
**Tasks**:
- [ ] `ConsoleTemplateEngine` implementieren
- Processor Pipeline (ähnlich wie View\Engine)
- Sequential Processing
- Processor Registry
- Error Handling
- [ ] `ConsoleTemplateLoader`
- Template-Files laden aus `/templates/console/`
- File Extension: `.console.txt` oder `.console.tpl`
- Template Caching (optional)
- Template Not Found Exception
- [ ] Template Syntax Documentation
- Placeholder Syntax
- Component Tags
- Loop Syntax
- Examples
**Files**:
- `src/Framework/Console/Template/ConsoleTemplateEngine.php`
- `src/Framework/Console/Template/Loading/ConsoleTemplateLoader.php`
- `docs/console-template-syntax.md`
### 2.3 Console Component Tags
**Ziel**: `<console:table>`, `<console:box>` etc. in Templates
**Tasks**:
- [ ] `ConsoleComponentTagProcessor` implementieren
- Parse `<console:*>` Tags
- Extract Attributes
- Extract Content
- Render via Component Registry
- [ ] `ConsoleComponentRegistry`
- Registry für Component-Mapping
- `table` → TableAdapter
- `box` → TextBoxAdapter
- `menu` → MenuAdapter
- `progress` → ProgressBarAdapter
- [ ] Console Component Adapters (Template-friendly)
- `ConsoleTableComponent`
- `ConsoleBoxComponent`
- `ConsoleMenuComponent`
- `ConsoleProgressComponent`
**Features**:
- Template Tag: `<console:table headers="A,B,C">...</console:table>`
- Nested Content Processing (für Loops in Attributen)
- Attribute Parsing
**Files**:
- `src/Framework/Console/Template/Processors/ConsoleComponentTagProcessor.php`
- `src/Framework/Console/Template/Components/ConsoleComponentRegistry.php`
- `src/Framework/Console/Template/Components/ConsoleTableComponent.php`
- `src/Framework/Console/Template/Components/ConsoleBoxComponent.php`
### 2.4 Template Response Integration
**Ziel**: ConsoleTemplateResponse nutzt Template-System
**Tasks**:
- [ ] `ConsoleTemplateResponse` finalisieren
- Integration mit ConsoleTemplateEngine
- Template Loading
- Data Binding
- Error Handling
- [ ] Template Examples erstellen
- `migration-status.console.txt`
- `user-list.console.txt`
- `health-check.console.txt`
- `system-status.console.txt`
**Files**:
- `templates/console/migration-status.console.txt`
- `templates/console/user-list.console.txt`
- `templates/console/health-check.console.txt`
### 2.5 Tests Phase 2
**Ziel**: Template-System vollständig getestet
**Tasks**:
- [ ] Processor Tests
- PlaceholderProcessor mit verschiedenen Syntaxen
- ForProcessor mit Nested Loops
- ComponentTagProcessor mit allen Tags
- [ ] Integration Tests
- ConsoleTemplateEngine mit kompletten Templates
- ConsoleTemplateResponse Rendering
- Error Cases (Template Not Found, Parse Errors)
- [ ] Template Examples Tests
- Alle Template-Files rendern korrekt
- Data-Binding funktioniert
- Component Tags werden ersetzt
**Files**:
- `tests/Unit/Console/Template/*Test.php`
- `tests/Feature/Console/TemplateRenderingTest.php`
**Deliverables Phase 2**:
- ✅ String-based Template Processing System
- ✅ ConsoleTemplateEngine mit Processor Pipeline
- ✅ Console Component Tags Support
- ✅ Template Loader mit Caching
- ✅ Template Examples & Documentation
- ✅ Comprehensive Tests
---
## 🏗️ Phase 3: Component-Based Layout System (Woche 3) - OPTIONAL
### 3.1 ConsoleComponent Interface & Adapters
**Ziel**: Unified Interface für bestehende Console-Components
**Tasks**:
- [ ] `ConsoleComponent` Interface
- `render(ConsoleOutputInterface $output): void`
- Standard-Interface für alle Components
- [ ] Adapters für bestehende Components
- `TableAdapter` - Wrapper für mutable `Table`
- `TextBoxAdapter` - Wrapper für readonly `TextBox`
- `MenuAdapter` - Wrapper für `InteractiveMenu`
- `ProgressBarAdapter` - Wrapper für `ProgressBar`
- `SpinnerAdapter` - Wrapper für `Spinner`
**Benefits**:
- Readonly Adapters trotz mutable Original-Components
- Unified Interface für Layout-System
- Backward-Compatible
**Files**:
- `src/Framework/Console/Components/ConsoleComponent.php`
- `src/Framework/Console/Components/Adapters/TableAdapter.php`
- `src/Framework/Console/Components/Adapters/TextBoxAdapter.php`
- `src/Framework/Console/Components/Adapters/MenuAdapter.php`
- `src/Framework/Console/Components/Adapters/ProgressBarAdapter.php`
- `src/Framework/Console/Components/Adapters/SpinnerAdapter.php`
### 3.2 Layout & Section Value Objects
**Ziel**: Komposition von Components zu Layouts
**Tasks**:
- [ ] `ConsoleLayout` Value Object
- Array von ConsoleSections
- Sequential Rendering
- Readonly Class
- [ ] `ConsoleSection` Value Object
- ConsoleComponent + Style
- Margins, Padding, Borders
- Readonly Class
- [ ] `ConsoleSectionStyle` Value Object
- Margins (top, bottom)
- Padding
- Borders (top, bottom, divider)
- Background Colors (optional)
**Files**:
- `src/Framework/Console/Layout/ConsoleLayout.php`
- `src/Framework/Console/Layout/ConsoleSection.php`
- `src/Framework/Console/Layout/ConsoleSectionStyle.php`
### 3.3 Layout Builder (Fluent API)
**Ziel**: Einfache Layout-Erstellung
**Tasks**:
- [ ] `ConsoleLayoutBuilder`
- `addSection(ConsoleComponent): self`
- `addTable(array, array): self`
- `addBox(string, ?string): self`
- `addDivider(): self`
- `addSpacing(int): self`
- `build(): ConsoleLayout`
**Files**:
- `src/Framework/Console/Layout/ConsoleLayoutBuilder.php`
### 3.4 Tests Phase 3
**Tasks**:
- [ ] Component Adapter Tests
- [ ] Layout Composition Tests
- [ ] Builder Tests
- [ ] Integration Tests
**Deliverables Phase 3**:
- ✅ ConsoleComponent Interface & 5 Adapters
- ✅ ConsoleLayout System
- ✅ ConsoleLayoutBuilder Fluent API
- ✅ Tests & Documentation
---
## 📚 Documentation & Examples
### Documentation Tasks
- [ ] Console Response Guide
- Alle Response-Typen mit Beispielen
- Migration Guide (ExitCode → ConsoleResponse)
- Best Practices
- [ ] Console Template Guide
- Template Syntax Reference
- Component Tags Reference
- Template Examples
- [ ] Console Layout Guide
- Component-Based Layouts
- Builder Pattern Examples
- Advanced Compositions
### Example Commands
- [ ] Simple Response Examples
- TextResponse in verschiedenen Commands
- TableResponse für Listen
- TemplateResponse für komplexe Ausgaben
- [ ] Template Examples
- Migration Status Template
- User List Template
- Health Check Template
- System Status Template
- [ ] Layout Examples
- Dashboard Layout
- Report Layout
- Multi-Section Layout
**Files**:
- `docs/console/console-response-guide.md`
- `docs/console/console-template-guide.md`
- `docs/console/console-layout-guide.md`
- `src/Framework/Console/Examples/*` (Update)
---
## 🧪 Testing Strategy
### Unit Tests
- [ ] Alle Response-Typen
- [ ] Alle Processors
- [ ] Alle Adapters
- [ ] Builder Classes
### Integration Tests
- [ ] ConsoleApplication mit verschiedenen Return-Typen
- [ ] Template Rendering End-to-End
- [ ] Layout Composition
- [ ] Backward Compatibility
### Example Tests
- [ ] Alle Example-Commands ausführbar
- [ ] Template-Examples rendern korrekt
- [ ] Layout-Examples funktionieren
**Coverage Goal**: ≥80%
---
## 🚀 Migration Strategy
### Backward Compatibility
- ✅ Alle bestehenden Commands funktionieren unverändert
- ✅ ExitCode Return-Type weiterhin supported
- ✅ Direktes Output-Schreiben weiterhin möglich
### Gradual Adoption
1. **Phase 1**: ConsoleResponse verfügbar, optional nutzbar
2. **Phase 2**: Template-System verfügbar, Commands können migrieren
3. **Phase 3**: Layout-System verfügbar für komplexe Use Cases
### Migration Patterns
```php
// Old: ExitCode + Direct Output
#[ConsoleCommand(name: 'old')]
public function old(ConsoleInput $input, ConsoleOutput $output): ExitCode
{
$output->writeLine("Done");
return ExitCode::SUCCESS;
}
// New: ConsoleResponse
#[ConsoleCommand(name: 'new')]
public function new(ConsoleInput $input): ConsoleResponse
{
return ConsoleTextResponse::success("Done");
}
// Transition: Both
#[ConsoleCommand(name: 'transition')]
public function transition(ConsoleInput $input, ConsoleOutput $output): ConsoleResponse
{
$output->writeLine("Processing..."); // Progress output
return ConsoleTextResponse::success("Done"); // Final result
}
```
---
## ✅ Success Criteria
### Phase 1 Complete When:
- [ ] All 6 Response-Typen implementiert und getestet
- [ ] ConsoleResponseBuilder funktional
- [ ] ConsoleApplication unterstützt beide Return-Typen
- [ ] ≥80% Test Coverage
- [ ] Documentation vollständig
### Phase 2 Complete When:
- [ ] Template-System funktional (Placeholder, For, Component Tags)
- [ ] ConsoleTemplateResponse integriert
- [ ] Template-Examples funktionieren
- [ ] ≥80% Test Coverage
- [ ] Documentation vollständig
### Phase 3 Complete When:
- [ ] Component Adapters funktional
- [ ] Layout-System implementiert
- [ ] Builder Pattern verfügbar
- [ ] ≥80% Test Coverage
- [ ] Documentation vollständig
---
## 🎯 Quick Start (Phase 1 only - Minimum Viable)
**Minimal Implementation für sofortige Nutzbarkeit**:
1. ConsoleResponse Interface
2. ConsoleTextResponse (mit Factory Methods)
3. ConsoleTableResponse
4. ConsoleCompositeResponse
5. ConsoleResponseBuilder
6. ConsoleApplication Update
**Result**: Commands können sofort ConsoleResponse nutzen ohne Template-System!
---
## 📊 Timeline Estimate
- **Phase 1**: 1 Woche (Foundation - ESSENTIAL)
- **Phase 2**: 1 Woche (Template System - RECOMMENDED)
- **Phase 3**: 1 Woche (Layout System - OPTIONAL)
**Minimum Viable**: Phase 1 only (1 Woche)
**Recommended**: Phase 1 + 2 (2 Wochen)
**Complete**: Phase 1 + 2 + 3 (3 Wochen)
---
## 🔗 Related Systems
### Integration Points
- **Console Module**: Bestehende Components (Table, TextBox, Menu, etc.)
- **View System**: Template-Processor-Pattern wiederverwenden
- **HTTP System**: Response-Pattern analog zu JsonResponse, ViewResult
- **Testing**: Pest Framework für alle Tests
### Dependencies
- Bestehende Console Components (keine Änderungen)
- ConsoleOutput Interface (keine Änderungen)
- ExitCode Enum (keine Änderungen)
- ConsoleStyle, ConsoleColor (keine Änderungen)
---
## 📝 Notes & Decisions
### Design Decisions
1. **String-based Templates** (nicht DOM) - Einfacher für Console-Output
2. **Method-based Commands** - Kompatibel mit `#[ConsoleCommand]` Attribute
3. **Backward Compatible** - Beide Return-Typen (ExitCode | ConsoleResponse)
4. **Adapter Pattern** - Wrapper für bestehende mutable Components
5. **Composition** - Layout aus Components komponieren, nicht erben
### Open Questions
- [ ] Template-Caching Strategy?
- [ ] Performance-Optimierung für große Outputs?
- [ ] ANSI-Code-Handling in Templates?
- [ ] Interactive Components in Templates?
### Future Enhancements
- Progress Bars in Templates
- Animated Spinners in Templates
- Color Themes für Templates
- Template Inheritance/Extends
- Custom Template Functions

View File

@@ -0,0 +1,33 @@
# Gitea Actions Artifact Compatibility Issue
## Problem
Gitea Actions verwendet eine GHES (GitHub Enterprise Server) kompatible API. Die `@actions/artifact` Actions v2.0.0+ (insbesondere `upload-artifact@v4` und `download-artifact@v4`) werden auf GHES nicht unterstützt.
### Fehlermeldung
```
GHESNotSupportedError: @actions/artifact v2.0.0+, upload-artifact@v4+ and download-artifact@v4+ are not currently supported on GHES.
```
## Lösung
Verwende **v3** Versionen der Artifact Actions:
- `actions/upload-artifact@v3` (statt `@v4`)
- `actions/download-artifact@v3` (statt `@v4`)
## Betroffene Workflows
- `.gitea/workflows/build-image.yml` - 12 Vorkommen
- `.gitea/workflows/monitor-performance.yml` - 1 Vorkommen
## Migration
Alle `@v4` Versionen wurden auf `@v3` downgraded. Die v3 Versionen sind vollständig kompatibel mit Gitea Actions und bieten die gleiche Funktionalität.
## Referenzen
- [Gitea Actions Documentation](https://docs.gitea.com/usage/actions/overview)
- [GitHub Actions Artifact v3 Documentation](https://github.com/actions/upload-artifact/tree/v3)