@heytherevibin/skillforge 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/CODE_OF_CONDUCT.md +34 -0
- package/CONTRIBUTING.md +38 -0
- package/LICENSE +21 -0
- package/README.md +337 -0
- package/RELEASING.md +93 -0
- package/SECURITY.md +31 -0
- package/STRATEGY.md +26 -0
- package/bin/cli.js +547 -0
- package/lib/packs.js +184 -0
- package/package.json +38 -0
- package/python/app/__init__.py +0 -0
- package/python/app/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/app/__pycache__/auth.cpython-312.pyc +0 -0
- package/python/app/__pycache__/main.cpython-312.pyc +0 -0
- package/python/app/auth.py +63 -0
- package/python/app/cli.py +78 -0
- package/python/app/db_paths.py +26 -0
- package/python/app/events_cli.py +175 -0
- package/python/app/main.py +647 -0
- package/python/app/materialize.py +138 -0
- package/python/app/mcp_server.py +610 -0
- package/python/app/route_cli.py +117 -0
- package/python/requirements-dev.txt +1 -0
- package/python/requirements.txt +7 -0
- package/python/tests/test_db_paths.py +41 -0
- package/skills/accessibility/SKILL.md +145 -0
- package/skills/agent-architecture-audit/SKILL.md +256 -0
- package/skills/agent-eval/SKILL.md +144 -0
- package/skills/agent-harness-construction/SKILL.md +72 -0
- package/skills/agent-introspection-debugging/SKILL.md +152 -0
- package/skills/agent-payment-x402/SKILL.md +224 -0
- package/skills/agent-sort/SKILL.md +214 -0
- package/skills/agentic-engineering/SKILL.md +62 -0
- package/skills/agentic-os/SKILL.md +386 -0
- package/skills/ai-first-engineering/SKILL.md +50 -0
- package/skills/ai-regression-testing/SKILL.md +384 -0
- package/skills/android-clean-architecture/SKILL.md +338 -0
- package/skills/angular-developer/SKILL.md +153 -0
- package/skills/angular-developer/references/angular-animations.md +160 -0
- package/skills/angular-developer/references/angular-aria.md +410 -0
- package/skills/angular-developer/references/cli.md +86 -0
- package/skills/angular-developer/references/component-harnesses.md +59 -0
- package/skills/angular-developer/references/component-styling.md +91 -0
- package/skills/angular-developer/references/components.md +117 -0
- package/skills/angular-developer/references/creating-services.md +97 -0
- package/skills/angular-developer/references/data-resolvers.md +69 -0
- package/skills/angular-developer/references/define-routes.md +67 -0
- package/skills/angular-developer/references/defining-providers.md +72 -0
- package/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/skills/angular-developer/references/e2e-testing.md +56 -0
- package/skills/angular-developer/references/effects.md +83 -0
- package/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/skills/angular-developer/references/host-elements.md +80 -0
- package/skills/angular-developer/references/injection-context.md +63 -0
- package/skills/angular-developer/references/inputs.md +101 -0
- package/skills/angular-developer/references/linked-signal.md +59 -0
- package/skills/angular-developer/references/loading-strategies.md +61 -0
- package/skills/angular-developer/references/mcp.md +108 -0
- package/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/skills/angular-developer/references/outputs.md +86 -0
- package/skills/angular-developer/references/reactive-forms.md +122 -0
- package/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/skills/angular-developer/references/resource.md +77 -0
- package/skills/angular-developer/references/route-animations.md +56 -0
- package/skills/angular-developer/references/route-guards.md +52 -0
- package/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/skills/angular-developer/references/router-testing.md +87 -0
- package/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/skills/angular-developer/references/signal-forms.md +795 -0
- package/skills/angular-developer/references/signals-overview.md +94 -0
- package/skills/angular-developer/references/tailwind-css.md +69 -0
- package/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/skills/angular-developer/references/testing-fundamentals.md +65 -0
- package/skills/api-connector-builder/SKILL.md +120 -0
- package/skills/api-design/SKILL.md +522 -0
- package/skills/architecture-decision-records/SKILL.md +178 -0
- package/skills/article-writing/SKILL.md +78 -0
- package/skills/automation-audit-ops/SKILL.md +141 -0
- package/skills/autonomous-agent-harness/SKILL.md +272 -0
- package/skills/autonomous-loops/SKILL.md +609 -0
- package/skills/backend-patterns/SKILL.md +560 -0
- package/skills/benchmark/SKILL.md +92 -0
- package/skills/blueprint/SKILL.md +104 -0
- package/skills/browser-qa/SKILL.md +86 -0
- package/skills/bun-runtime/SKILL.md +83 -0
- package/skills/canary-watch/SKILL.md +98 -0
- package/skills/carrier-relationship-management/SKILL.md +211 -0
- package/skills/cisco-ios-patterns/SKILL.md +163 -0
- package/skills/ck/SKILL.md +147 -0
- package/skills/ck/commands/forget.mjs +44 -0
- package/skills/ck/commands/info.mjs +24 -0
- package/skills/ck/commands/init.mjs +143 -0
- package/skills/ck/commands/list.mjs +40 -0
- package/skills/ck/commands/migrate.mjs +202 -0
- package/skills/ck/commands/resume.mjs +36 -0
- package/skills/ck/commands/save.mjs +210 -0
- package/skills/ck/commands/shared.mjs +387 -0
- package/skills/ck/hooks/session-start.mjs +224 -0
- package/skills/claude-devfleet/SKILL.md +103 -0
- package/skills/click-path-audit/SKILL.md +244 -0
- package/skills/clickhouse-io/SKILL.md +438 -0
- package/skills/code-tour/SKILL.md +235 -0
- package/skills/codebase-onboarding/SKILL.md +232 -0
- package/skills/coding-standards/SKILL.md +548 -0
- package/skills/compose-multiplatform-patterns/SKILL.md +298 -0
- package/skills/connections-optimizer/SKILL.md +188 -0
- package/skills/content-engine/SKILL.md +126 -0
- package/skills/content-hash-cache-pattern/SKILL.md +160 -0
- package/skills/context-budget/SKILL.md +134 -0
- package/skills/continuous-agent-loop/SKILL.md +44 -0
- package/skills/continuous-learning/SKILL.md +129 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +69 -0
- package/skills/continuous-learning-v2/SKILL.md +358 -0
- package/skills/continuous-learning-v2/agents/observer-loop.sh +322 -0
- package/skills/continuous-learning-v2/agents/observer.md +198 -0
- package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
- package/skills/continuous-learning-v2/agents/start-observer.sh +248 -0
- package/skills/continuous-learning-v2/config.json +8 -0
- package/skills/continuous-learning-v2/hooks/observe.sh +476 -0
- package/skills/continuous-learning-v2/scripts/detect-project.sh +288 -0
- package/skills/continuous-learning-v2/scripts/instinct-cli.py +1519 -0
- package/skills/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
- package/skills/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
- package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +1018 -0
- package/skills/cost-aware-llm-pipeline/SKILL.md +182 -0
- package/skills/cost-tracking/SKILL.md +147 -0
- package/skills/council/SKILL.md +202 -0
- package/skills/cpp-coding-standards/SKILL.md +722 -0
- package/skills/cpp-testing/SKILL.md +323 -0
- package/skills/crosspost/SKILL.md +110 -0
- package/skills/csharp-testing/SKILL.md +320 -0
- package/skills/customer-billing-ops/SKILL.md +139 -0
- package/skills/customs-trade-compliance/SKILL.md +262 -0
- package/skills/dart-flutter-patterns/SKILL.md +562 -0
- package/skills/dashboard-builder/SKILL.md +108 -0
- package/skills/data-scraper-agent/SKILL.md +764 -0
- package/skills/database-migrations/SKILL.md +428 -0
- package/skills/deep-research/SKILL.md +158 -0
- package/skills/defi-amm-security/SKILL.md +166 -0
- package/skills/deployment-patterns/SKILL.md +426 -0
- package/skills/design-system/SKILL.md +81 -0
- package/skills/django-celery/SKILL.md +456 -0
- package/skills/django-patterns/SKILL.md +733 -0
- package/skills/django-security/SKILL.md +592 -0
- package/skills/django-tdd/SKILL.md +728 -0
- package/skills/django-verification/SKILL.md +468 -0
- package/skills/dmux-workflows/SKILL.md +190 -0
- package/skills/docker-patterns/SKILL.md +363 -0
- package/skills/documentation-lookup/SKILL.md +89 -0
- package/skills/dotnet-patterns/SKILL.md +320 -0
- package/skills/e2e-testing/SKILL.md +325 -0
- package/skills/email-ops/SKILL.md +120 -0
- package/skills/energy-procurement/SKILL.md +227 -0
- package/skills/enterprise-agent-ops/SKILL.md +49 -0
- package/skills/error-handling/SKILL.md +375 -0
- package/skills/eval-harness/SKILL.md +269 -0
- package/skills/evm-token-decimals/SKILL.md +130 -0
- package/skills/exa-search/SKILL.md +106 -0
- package/skills/fal-ai-media/SKILL.md +287 -0
- package/skills/fastapi-patterns/SKILL.md +327 -0
- package/skills/finance-billing-ops/SKILL.md +126 -0
- package/skills/flox-environments/SKILL.md +496 -0
- package/skills/flutter-dart-code-review/SKILL.md +434 -0
- package/skills/foundation-models-on-device/SKILL.md +243 -0
- package/skills/frontend-design-direction/SKILL.md +92 -0
- package/skills/frontend-patterns/SKILL.md +641 -0
- package/skills/frontend-slides/SKILL.md +183 -0
- package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/skills/frontend-slides/animation-patterns.md +122 -0
- package/skills/frontend-slides/html-template.md +419 -0
- package/skills/frontend-slides/scripts/export-pdf.sh +418 -0
- package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
- package/skills/frontend-slides/viewport-base.css +153 -0
- package/skills/fsharp-testing/SKILL.md +279 -0
- package/skills/gan-style-harness/SKILL.md +278 -0
- package/skills/gateguard/SKILL.md +125 -0
- package/skills/git-workflow/SKILL.md +714 -0
- package/skills/github-ops/SKILL.md +143 -0
- package/skills/golang-patterns/SKILL.md +673 -0
- package/skills/golang-testing/SKILL.md +719 -0
- package/skills/google-workspace-ops/SKILL.md +94 -0
- package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
- package/skills/healthcare-emr-patterns/SKILL.md +159 -0
- package/skills/healthcare-eval-harness/SKILL.md +207 -0
- package/skills/healthcare-phi-compliance/SKILL.md +145 -0
- package/skills/hermes-imports/SKILL.md +87 -0
- package/skills/hexagonal-architecture/SKILL.md +275 -0
- package/skills/hipaa-compliance/SKILL.md +78 -0
- package/skills/homelab-network-readiness/SKILL.md +169 -0
- package/skills/homelab-network-setup/SKILL.md +129 -0
- package/skills/homelab-pihole-dns/SKILL.md +274 -0
- package/skills/homelab-vlan-segmentation/SKILL.md +311 -0
- package/skills/homelab-wireguard-vpn/SKILL.md +305 -0
- package/skills/hookify-rules/SKILL.md +128 -0
- package/skills/inventory-demand-planning/SKILL.md +246 -0
- package/skills/investor-materials/SKILL.md +95 -0
- package/skills/investor-outreach/SKILL.md +90 -0
- package/skills/ios-icon-gen/SKILL.md +157 -0
- package/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/skills/iterative-retrieval/SKILL.md +209 -0
- package/skills/java-coding-standards/SKILL.md +382 -0
- package/skills/jira-integration/SKILL.md +292 -0
- package/skills/jpa-patterns/SKILL.md +150 -0
- package/skills/knowledge-ops/SKILL.md +153 -0
- package/skills/kotlin-coroutines-flows/SKILL.md +283 -0
- package/skills/kotlin-exposed-patterns/SKILL.md +718 -0
- package/skills/kotlin-ktor-patterns/SKILL.md +688 -0
- package/skills/kotlin-patterns/SKILL.md +710 -0
- package/skills/kotlin-testing/SKILL.md +823 -0
- package/skills/laravel-patterns/SKILL.md +414 -0
- package/skills/laravel-plugin-discovery/SKILL.md +228 -0
- package/skills/laravel-security/SKILL.md +284 -0
- package/skills/laravel-tdd/SKILL.md +282 -0
- package/skills/laravel-verification/SKILL.md +178 -0
- package/skills/lead-intelligence/SKILL.md +320 -0
- package/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
- package/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
- package/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
- package/skills/lead-intelligence/agents/signal-scorer.md +60 -0
- package/skills/liquid-glass-design/SKILL.md +279 -0
- package/skills/llm-trading-agent-security/SKILL.md +146 -0
- package/skills/logistics-exception-management/SKILL.md +221 -0
- package/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/skills/manim-video/SKILL.md +88 -0
- package/skills/manim-video/assets/network_graph_scene.py +52 -0
- package/skills/market-research/SKILL.md +74 -0
- package/skills/mcp-server-patterns/SKILL.md +68 -0
- package/skills/messages-ops/SKILL.md +103 -0
- package/skills/mle-workflow/SKILL.md +345 -0
- package/skills/motion-advanced/SKILL.md +596 -0
- package/skills/motion-foundations/SKILL.md +299 -0
- package/skills/motion-patterns/SKILL.md +435 -0
- package/skills/motion-ui/SKILL.md +574 -0
- package/skills/mysql-patterns/SKILL.md +411 -0
- package/skills/nanoclaw-repl/SKILL.md +32 -0
- package/skills/nestjs-patterns/SKILL.md +229 -0
- package/skills/netmiko-ssh-automation/SKILL.md +173 -0
- package/skills/network-bgp-diagnostics/SKILL.md +167 -0
- package/skills/network-config-validation/SKILL.md +210 -0
- package/skills/network-interface-health/SKILL.md +152 -0
- package/skills/nextjs-turbopack/SKILL.md +43 -0
- package/skills/nodejs-keccak256/SKILL.md +102 -0
- package/skills/nutrient-document-processing/SKILL.md +166 -0
- package/skills/nuxt4-patterns/SKILL.md +99 -0
- package/skills/openclaw-persona-forge/SKILL.md +288 -0
- package/skills/openclaw-persona-forge/gacha.py +224 -0
- package/skills/openclaw-persona-forge/gacha.sh +5 -0
- package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
- package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
- package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
- package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
- package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
- package/skills/openclaw-persona-forge/references/output-template.md +166 -0
- package/skills/opensource-pipeline/SKILL.md +254 -0
- package/skills/perl-patterns/SKILL.md +503 -0
- package/skills/perl-security/SKILL.md +502 -0
- package/skills/perl-testing/SKILL.md +474 -0
- package/skills/plan-orchestrate/SKILL.md +253 -0
- package/skills/plankton-code-quality/SKILL.md +236 -0
- package/skills/postgres-patterns/SKILL.md +146 -0
- package/skills/product-capability/SKILL.md +140 -0
- package/skills/product-lens/SKILL.md +91 -0
- package/skills/production-audit/SKILL.md +206 -0
- package/skills/production-scheduling/SKILL.md +237 -0
- package/skills/project-flow-ops/SKILL.md +110 -0
- package/skills/prompt-optimizer/SKILL.md +398 -0
- package/skills/python-patterns/SKILL.md +749 -0
- package/skills/python-testing/SKILL.md +815 -0
- package/skills/pytorch-patterns/SKILL.md +395 -0
- package/skills/quality-nonconformance/SKILL.md +259 -0
- package/skills/quarkus-patterns/SKILL.md +721 -0
- package/skills/quarkus-security/SKILL.md +466 -0
- package/skills/quarkus-tdd/SKILL.md +810 -0
- package/skills/quarkus-verification/SKILL.md +478 -0
- package/skills/ralphinho-rfc-pipeline/SKILL.md +66 -0
- package/skills/redis-patterns/SKILL.md +402 -0
- package/skills/regex-vs-llm-structured-text/SKILL.md +219 -0
- package/skills/remotion-video-creation/SKILL.md +43 -0
- package/skills/remotion-video-creation/rules/3d.md +86 -0
- package/skills/remotion-video-creation/rules/animations.md +29 -0
- package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/skills/remotion-video-creation/rules/assets.md +78 -0
- package/skills/remotion-video-creation/rules/audio.md +172 -0
- package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
- package/skills/remotion-video-creation/rules/can-decode.md +75 -0
- package/skills/remotion-video-creation/rules/charts.md +58 -0
- package/skills/remotion-video-creation/rules/compositions.md +146 -0
- package/skills/remotion-video-creation/rules/display-captions.md +126 -0
- package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
- package/skills/remotion-video-creation/rules/fonts.md +152 -0
- package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
- package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
- package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
- package/skills/remotion-video-creation/rules/gifs.md +138 -0
- package/skills/remotion-video-creation/rules/images.md +130 -0
- package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
- package/skills/remotion-video-creation/rules/lottie.md +67 -0
- package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
- package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
- package/skills/remotion-video-creation/rules/sequencing.md +106 -0
- package/skills/remotion-video-creation/rules/tailwind.md +11 -0
- package/skills/remotion-video-creation/rules/text-animations.md +20 -0
- package/skills/remotion-video-creation/rules/timing.md +179 -0
- package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
- package/skills/remotion-video-creation/rules/transitions.md +122 -0
- package/skills/remotion-video-creation/rules/trimming.md +52 -0
- package/skills/remotion-video-creation/rules/videos.md +171 -0
- package/skills/repo-scan/SKILL.md +78 -0
- package/skills/research-ops/SKILL.md +111 -0
- package/skills/returns-reverse-logistics/SKILL.md +239 -0
- package/skills/rules-distill/SKILL.md +263 -0
- package/skills/rules-distill/scripts/scan-rules.sh +58 -0
- package/skills/rules-distill/scripts/scan-skills.sh +129 -0
- package/skills/rust-patterns/SKILL.md +498 -0
- package/skills/rust-testing/SKILL.md +499 -0
- package/skills/safety-guard/SKILL.md +74 -0
- package/skills/santa-method/SKILL.md +306 -0
- package/skills/scientific-db-pubmed-database/SKILL.md +175 -0
- package/skills/scientific-db-uspto-database/SKILL.md +177 -0
- package/skills/scientific-pkg-gget/SKILL.md +166 -0
- package/skills/scientific-thinking-literature-review/SKILL.md +192 -0
- package/skills/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
- package/skills/search-first/SKILL.md +181 -0
- package/skills/security-bounty-hunter/SKILL.md +99 -0
- package/skills/security-review/SKILL.md +502 -0
- package/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/skills/seo/SKILL.md +153 -0
- package/skills/skill-comply/SKILL.md +57 -0
- package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
- package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
- package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
- package/skills/skill-comply/prompts/classifier.md +24 -0
- package/skills/skill-comply/prompts/scenario_generator.md +62 -0
- package/skills/skill-comply/prompts/spec_generator.md +42 -0
- package/skills/skill-comply/pyproject.toml +15 -0
- package/skills/skill-comply/scripts/__init__.py +0 -0
- package/skills/skill-comply/scripts/classifier.py +85 -0
- package/skills/skill-comply/scripts/grader.py +124 -0
- package/skills/skill-comply/scripts/parser.py +107 -0
- package/skills/skill-comply/scripts/report.py +170 -0
- package/skills/skill-comply/scripts/run.py +127 -0
- package/skills/skill-comply/scripts/runner.py +186 -0
- package/skills/skill-comply/scripts/scenario_generator.py +70 -0
- package/skills/skill-comply/scripts/spec_generator.py +72 -0
- package/skills/skill-comply/scripts/utils.py +13 -0
- package/skills/skill-comply/tests/test_grader.py +197 -0
- package/skills/skill-comply/tests/test_parser.py +90 -0
- package/skills/skill-comply/tests/test_runner.py +172 -0
- package/skills/skill-scout/SKILL.md +139 -0
- package/skills/skill-stocktake/SKILL.md +193 -0
- package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
- package/skills/skill-stocktake/scripts/save-results.sh +56 -0
- package/skills/skill-stocktake/scripts/scan.sh +170 -0
- package/skills/social-graph-ranker/SKILL.md +153 -0
- package/skills/springboot-patterns/SKILL.md +313 -0
- package/skills/springboot-security/SKILL.md +271 -0
- package/skills/springboot-tdd/SKILL.md +157 -0
- package/skills/springboot-verification/SKILL.md +230 -0
- package/skills/strategic-compact/SKILL.md +129 -0
- package/skills/strategic-compact/suggest-compact.sh +54 -0
- package/skills/swift-actor-persistence/SKILL.md +142 -0
- package/skills/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/swift-protocol-di-testing/SKILL.md +189 -0
- package/skills/swiftui-patterns/SKILL.md +259 -0
- package/skills/tdd-workflow/SKILL.md +462 -0
- package/skills/team-builder/SKILL.md +166 -0
- package/skills/terminal-ops/SKILL.md +108 -0
- package/skills/tinystruct-patterns/SKILL.md +130 -0
- package/skills/tinystruct-patterns/references/architecture.md +77 -0
- package/skills/tinystruct-patterns/references/data-handling.md +35 -0
- package/skills/tinystruct-patterns/references/routing.md +57 -0
- package/skills/tinystruct-patterns/references/system-usage.md +74 -0
- package/skills/tinystruct-patterns/references/testing.md +59 -0
- package/skills/token-budget-advisor/SKILL.md +133 -0
- package/skills/ui-demo/SKILL.md +464 -0
- package/skills/ui-to-vue/SKILL.md +134 -0
- package/skills/unified-notifications-ops/SKILL.md +186 -0
- package/skills/verification-loop/SKILL.md +125 -0
- package/skills/video-editing/SKILL.md +309 -0
- package/skills/videodb/SKILL.md +373 -0
- package/skills/videodb/reference/api-reference.md +550 -0
- package/skills/videodb/reference/capture-reference.md +407 -0
- package/skills/videodb/reference/capture.md +101 -0
- package/skills/videodb/reference/editor.md +443 -0
- package/skills/videodb/reference/generative.md +331 -0
- package/skills/videodb/reference/rtstream-reference.md +564 -0
- package/skills/videodb/reference/rtstream.md +65 -0
- package/skills/videodb/reference/search.md +230 -0
- package/skills/videodb/reference/streaming.md +406 -0
- package/skills/videodb/reference/use-cases.md +118 -0
- package/skills/videodb/scripts/ws_listener.py +282 -0
- package/skills/visa-doc-translate/README.md +86 -0
- package/skills/visa-doc-translate/SKILL.md +117 -0
- package/skills/vite-patterns/SKILL.md +448 -0
- package/skills/windows-desktop-e2e/SKILL.md +787 -0
- package/skills/workspace-surface-audit/SKILL.md +124 -0
- package/skills/x-api/SKILL.md +233 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Components
|
|
2
|
+
|
|
3
|
+
Angular components are the fundamental building blocks of an application. Each component consists of a TypeScript class with behaviors, an HTML template, and a CSS selector.
|
|
4
|
+
|
|
5
|
+
## Component Definition
|
|
6
|
+
|
|
7
|
+
Use the `@Component` decorator to define a component's metadata.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
@Component({
|
|
11
|
+
selector: 'app-profile',
|
|
12
|
+
template: `
|
|
13
|
+
<img src="profile.jpg" alt="Profile photo" />
|
|
14
|
+
<button (click)="save()">Save</button>
|
|
15
|
+
`,
|
|
16
|
+
styles: `
|
|
17
|
+
img {
|
|
18
|
+
border-radius: 50%;
|
|
19
|
+
}
|
|
20
|
+
`,
|
|
21
|
+
})
|
|
22
|
+
export class Profile {
|
|
23
|
+
save() {
|
|
24
|
+
/* ... */
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Metadata Options
|
|
30
|
+
|
|
31
|
+
- `selector`: The CSS selector that identifies this component in templates.
|
|
32
|
+
- `template`: Inline HTML template (preferred for small templates).
|
|
33
|
+
- `templateUrl`: Path to an external HTML file.
|
|
34
|
+
- `styles`: Inline CSS styles.
|
|
35
|
+
- `styleUrl` / `styleUrls`: Path(s) to external CSS file(s).
|
|
36
|
+
- `imports`: Lists the components, directives, or pipes used in this component's template.
|
|
37
|
+
|
|
38
|
+
## Using Components
|
|
39
|
+
|
|
40
|
+
To use a component, add it to the `imports` array of the consuming component and use its selector in the template.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
@Component({
|
|
44
|
+
selector: 'app-root',
|
|
45
|
+
imports: [Profile],
|
|
46
|
+
template: `<app-profile />`,
|
|
47
|
+
})
|
|
48
|
+
export class App {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Template Control Flow
|
|
52
|
+
|
|
53
|
+
Angular uses built-in blocks for conditional rendering and loops.
|
|
54
|
+
|
|
55
|
+
### Conditional Rendering (`@if`)
|
|
56
|
+
|
|
57
|
+
Use `@if` to conditionally show content. You can include `@else if` and `@else` blocks.
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
@if (user.isAdmin) {
|
|
61
|
+
<admin-dashboard />
|
|
62
|
+
} @else if (user.isModerator) {
|
|
63
|
+
<mod-dashboard />
|
|
64
|
+
} @else {
|
|
65
|
+
<standard-dashboard />
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Result aliasing**: Save the result of the expression for reuse.
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
@if (user.settings(); as settings) {
|
|
73
|
+
<p>Theme: {{ settings.theme }}</p>
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Loops (`@for`)
|
|
78
|
+
|
|
79
|
+
The `@for` block iterates over collections. The `track` expression is **required** for performance and DOM reuse.
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<ul>
|
|
83
|
+
@for (item of items(); track item.id; let i = $index, total = $count) {
|
|
84
|
+
<li>{{ i + 1 }}/{{ total }}: {{ item.name }}</li>
|
|
85
|
+
} @empty {
|
|
86
|
+
<li>No items to display.</li>
|
|
87
|
+
}
|
|
88
|
+
</ul>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Implicit Variables**: `$index`, `$count`, `$first`, `$last`, `$even`, `$odd`.
|
|
92
|
+
|
|
93
|
+
### Switching Content (`@switch`)
|
|
94
|
+
|
|
95
|
+
The `@switch` block renders content based on a value. It uses strict equality (`===`) and has **no fallthrough**.
|
|
96
|
+
|
|
97
|
+
```html
|
|
98
|
+
@switch (status()) { @case ('loading') { <app-spinner /> } @case ('error') { <app-error-msg /> }
|
|
99
|
+
@case ('success') { <app-data-grid /> } @default {
|
|
100
|
+
<p>Unknown status</p>
|
|
101
|
+
} }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Exhaustive Type Checking**: Use `@default never;` to ensure all cases of a union type are handled.
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
@switch (state) { @case ('on') { ... } @case ('off') { ... } @default never; // Errors if a new
|
|
108
|
+
state like 'standby' is added }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Core Concepts
|
|
112
|
+
|
|
113
|
+
- **Host Element**: The DOM element that matches the component's selector.
|
|
114
|
+
- **View**: The DOM rendered by the component's template inside the host element.
|
|
115
|
+
- **Standalone**: By default, components are standalone (since Angular 19, `standalone: true` is default). For older versions, `standalone: true` must be explicit or the component must be part of an `NgModule`.
|
|
116
|
+
- **Component Tree**: Angular applications are structured as a tree of components, where each component can host child components.
|
|
117
|
+
- **Component Naming**: Do not add suffixes the `Component` suffix for Component classes (e.g., AppComponent) unless the project has been configured to use that naming configuration.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Creating and Using Services
|
|
2
|
+
|
|
3
|
+
Services in Angular are reusable pieces of code that handle data fetching, business logic, or state management that multiple components or other services need to access.
|
|
4
|
+
|
|
5
|
+
## Creating a Service
|
|
6
|
+
|
|
7
|
+
You can generate a service using the Angular CLI:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ng generate service my-data
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or you can manually create a TypeScript class and decorate it with `@Injectable()`.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import {Injectable} from '@angular/core';
|
|
17
|
+
|
|
18
|
+
@Injectable({
|
|
19
|
+
providedIn: 'root',
|
|
20
|
+
})
|
|
21
|
+
export class BasicDataStore {
|
|
22
|
+
private data: string[] = [];
|
|
23
|
+
|
|
24
|
+
addData(item: string): void {
|
|
25
|
+
this.data.push(item);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getData(): string[] {
|
|
29
|
+
return [...this.data];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### The `providedIn: 'root'` Option
|
|
35
|
+
|
|
36
|
+
Using `providedIn: 'root'` is the recommended approach for most services. It tells Angular to:
|
|
37
|
+
|
|
38
|
+
- **Create a single instance (singleton)** for the entire application.
|
|
39
|
+
- **Make it available everywhere** automatically, without needing to list it in any `providers` array.
|
|
40
|
+
- **Enable tree-shaking**, meaning the service is only included in the final JavaScript bundle if it is actually injected somewhere.
|
|
41
|
+
|
|
42
|
+
## Injecting a Service
|
|
43
|
+
|
|
44
|
+
Once a service is created, you can inject it into components, directives, or other services using the `inject()` function.
|
|
45
|
+
|
|
46
|
+
### Injecting into a Component
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import {Component, inject} from '@angular/core';
|
|
50
|
+
import {BasicDataStore} from './basic-data-store.service';
|
|
51
|
+
|
|
52
|
+
@Component({
|
|
53
|
+
selector: 'app-example',
|
|
54
|
+
template: `
|
|
55
|
+
<div>
|
|
56
|
+
<p>Data items: {{ dataStore.getData().length }}</p>
|
|
57
|
+
<button (click)="dataStore.addData('New Item')">Add Item</button>
|
|
58
|
+
</div>
|
|
59
|
+
`,
|
|
60
|
+
})
|
|
61
|
+
export class Example {
|
|
62
|
+
// Inject the service as a class field
|
|
63
|
+
dataStore = inject(BasicDataStore);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Injecting into Another Service
|
|
68
|
+
|
|
69
|
+
Services can inject other services in the exact same way.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import {Injectable, inject} from '@angular/core';
|
|
73
|
+
import {AdvancedDataStore} from './advanced-data-store.service';
|
|
74
|
+
|
|
75
|
+
@Injectable({
|
|
76
|
+
providedIn: 'root',
|
|
77
|
+
})
|
|
78
|
+
export class BasicDataStore {
|
|
79
|
+
// Injecting another service
|
|
80
|
+
private advancedDataStore = inject(AdvancedDataStore);
|
|
81
|
+
|
|
82
|
+
private data: string[] = [];
|
|
83
|
+
|
|
84
|
+
getData(): string[] {
|
|
85
|
+
// Combine data from this service and the injected service
|
|
86
|
+
return [...this.data, ...this.advancedDataStore.getData()];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Advanced Service Patterns
|
|
92
|
+
|
|
93
|
+
While `providedIn: 'root'` covers most scenarios, you may sometimes need:
|
|
94
|
+
|
|
95
|
+
- **Component-specific instances**: If a component needs its own isolated instance of a service, provide it directly in the component's `@Component({ providers: [MyService] })` array.
|
|
96
|
+
- **Factory providers**: For dynamic creation.
|
|
97
|
+
- **Value providers**: For injecting configuration objects.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Data Resolvers
|
|
2
|
+
|
|
3
|
+
Data resolvers fetch data before a route activates, ensuring components have the necessary data upon rendering.
|
|
4
|
+
|
|
5
|
+
## Creating a Resolver
|
|
6
|
+
|
|
7
|
+
Implement the `ResolveFn` type.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export const userResolver: ResolveFn<User> = (route, state) => {
|
|
11
|
+
const userService = inject(UserService);
|
|
12
|
+
const id = route.paramMap.get('id')!;
|
|
13
|
+
return userService.getUser(id);
|
|
14
|
+
};
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuring the Route
|
|
18
|
+
|
|
19
|
+
Add the resolver under the `resolve` key.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
{
|
|
23
|
+
path: 'user/:id',
|
|
24
|
+
component: UserProfile,
|
|
25
|
+
resolve: {
|
|
26
|
+
user: userResolver
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Accessing Resolved Data
|
|
32
|
+
|
|
33
|
+
### 1. Via `ActivatedRoute` (Traditional)
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
private route = inject(ActivatedRoute);
|
|
37
|
+
data = toSignal(this.route.data);
|
|
38
|
+
user = computed(() => this.data().user);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Via Component Inputs (Modern)
|
|
42
|
+
|
|
43
|
+
Enable `withComponentInputBinding()` in `provideRouter` to pass resolved data directly to `@Input` or `input()`.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// app.config.ts
|
|
47
|
+
provideRouter(routes, withComponentInputBinding());
|
|
48
|
+
|
|
49
|
+
// component.ts
|
|
50
|
+
user = input.required<User>();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Error Handling
|
|
54
|
+
|
|
55
|
+
Navigation is blocked if a resolver fails.
|
|
56
|
+
|
|
57
|
+
- Use `withNavigationErrorHandler` for global handling.
|
|
58
|
+
- Use `catchError` within the resolver to return a `RedirectCommand` or fallback data.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
return userService
|
|
62
|
+
.get(id)
|
|
63
|
+
.pipe(catchError(() => of(new RedirectCommand(router.parseUrl('/error')))));
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Best Practices
|
|
67
|
+
|
|
68
|
+
- **Keep it lightweight**: Fetch only critical data.
|
|
69
|
+
- **Provide feedback**: Listen to router events to show a global loading bar during navigation, as the UI stays on the old page until the resolver finishes.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Define Routes
|
|
2
|
+
|
|
3
|
+
Routes are objects that define which component should render for a specific URL path.
|
|
4
|
+
|
|
5
|
+
## Basic Configuration
|
|
6
|
+
|
|
7
|
+
Define routes in a `Routes` array and provide them using `provideRouter` in your `appConfig`.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// app.routes.ts
|
|
11
|
+
export const routes: Routes = [
|
|
12
|
+
{path: '', component: HomePage},
|
|
13
|
+
{path: 'admin', component: AdminPage},
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
// app.config.ts
|
|
17
|
+
export const appConfig: ApplicationConfig = {
|
|
18
|
+
providers: [provideRouter(routes)],
|
|
19
|
+
};
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## URL Paths
|
|
23
|
+
|
|
24
|
+
- **Static**: Matches an exact string (e.g., `'admin'`).
|
|
25
|
+
- **Route Parameters**: Dynamic segments prefixed with a colon (e.g., `'user/:id'`).
|
|
26
|
+
- **Wildcard**: Matches any URL using `**`. Useful for "Not Found" pages. **Always place at the end of the array.**
|
|
27
|
+
|
|
28
|
+
## Matching Strategy
|
|
29
|
+
|
|
30
|
+
Angular uses a **first-match wins** strategy. Specific routes must come before less specific ones.
|
|
31
|
+
|
|
32
|
+
## Redirects
|
|
33
|
+
|
|
34
|
+
Use `redirectTo` to point one path to another.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
{ path: 'articles', redirectTo: '/blog' },
|
|
38
|
+
{ path: 'blog', component: Blog },
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Page Titles
|
|
42
|
+
|
|
43
|
+
Associate titles with routes for accessibility. Titles can be static or dynamic (via `ResolveFn` or a custom `TitleStrategy`).
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
{ path: 'home', component: Home, title: 'Home Page' }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Route Data and Providers
|
|
50
|
+
|
|
51
|
+
- **Static Data**: Attach metadata using the `data` property.
|
|
52
|
+
- **Route Providers**: Scope dependencies to a specific route and its children using the `providers` array.
|
|
53
|
+
|
|
54
|
+
## Nested (Child) Routes
|
|
55
|
+
|
|
56
|
+
Define sub-views using the `children` property. Parent components must include a `<router-outlet />`.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
{
|
|
60
|
+
path: 'product/:id',
|
|
61
|
+
component: Product,
|
|
62
|
+
children: [
|
|
63
|
+
{ path: 'info', component: ProductInfo },
|
|
64
|
+
{ path: 'reviews', component: ProductReviews },
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Defining Dependency Providers
|
|
2
|
+
|
|
3
|
+
Angular offers automatic and manual ways to provide dependencies to its Dependency Injection (DI) system.
|
|
4
|
+
|
|
5
|
+
## Automatic Provision
|
|
6
|
+
|
|
7
|
+
The most common way to provide a service is using `providedIn: 'root'` on an `@Injectable()`.
|
|
8
|
+
|
|
9
|
+
### InjectionToken
|
|
10
|
+
|
|
11
|
+
Use `InjectionToken` for non-class dependencies (configuration objects, functions, primitives). An `InjectionToken` can also be automatically provided.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import {InjectionToken} from '@angular/core';
|
|
15
|
+
|
|
16
|
+
export interface AppConfig {
|
|
17
|
+
apiUrl: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const APP_CONFIG = new InjectionToken<AppConfig>('app.config', {
|
|
21
|
+
providedIn: 'root',
|
|
22
|
+
factory: () => ({apiUrl: 'https://api.example.com'}),
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Manual Provision
|
|
27
|
+
|
|
28
|
+
You use the `providers` array when a service lacks `providedIn`, when you want a new instance for a specific component, or when configuring runtime values.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
@Component({
|
|
32
|
+
providers: [
|
|
33
|
+
// Shorthand for { provide: LocalService, useClass: LocalService }
|
|
34
|
+
LocalService,
|
|
35
|
+
|
|
36
|
+
// useClass: Swap implementations
|
|
37
|
+
{provide: Logger, useClass: BetterLogger},
|
|
38
|
+
|
|
39
|
+
// useValue: Provide static values
|
|
40
|
+
{provide: API_URL_TOKEN, useValue: 'https://api.example.com'},
|
|
41
|
+
|
|
42
|
+
// useFactory: Generate value dynamically
|
|
43
|
+
{
|
|
44
|
+
provide: ApiClient,
|
|
45
|
+
useFactory: (http = inject(HttpClient)) => new ApiClient(http),
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
// useExisting: Create an alias
|
|
49
|
+
{provide: OldLogger, useExisting: NewLogger},
|
|
50
|
+
|
|
51
|
+
// multi: Provide multiple values for the same token as an array
|
|
52
|
+
{provide: INTERCEPTOR_TOKEN, useClass: AuthInterceptor, multi: true},
|
|
53
|
+
],
|
|
54
|
+
})
|
|
55
|
+
export class Example {}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Scopes of Providers
|
|
59
|
+
|
|
60
|
+
- **Application Bootstrap**: Global singletons. Use for HTTP clients, logging, or app-wide config.
|
|
61
|
+
- **Component/Directive**: Isolated instances. Use for component-specific state or forms. Services are destroyed when the component is destroyed.
|
|
62
|
+
- **Route**: Feature-specific services loaded only with specific routes.
|
|
63
|
+
|
|
64
|
+
## Library Pattern: `provide*` functions
|
|
65
|
+
|
|
66
|
+
Library authors should export functions that return provider arrays to encapsulate configuration:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
export function provideAnalytics(config: AnalyticsConfig): Provider[] {
|
|
70
|
+
return [{provide: ANALYTICS_CONFIG, useValue: config}, AnalyticsService];
|
|
71
|
+
}
|
|
72
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Dependency Injection (DI) Fundamentals
|
|
2
|
+
|
|
3
|
+
Dependency Injection (DI) is a design pattern used to organize and share code across an application by allowing you to "inject" features into different parts. This improves code maintainability, scalability, and testability.
|
|
4
|
+
|
|
5
|
+
## How DI Works in Angular
|
|
6
|
+
|
|
7
|
+
There are two primary ways code interacts with Angular's DI system:
|
|
8
|
+
|
|
9
|
+
1. **Providing**: Making values (objects, functions, primitives) available to the DI system.
|
|
10
|
+
2. **Injecting**: Asking the DI system for those values.
|
|
11
|
+
|
|
12
|
+
Angular components, directives, and services automatically participate in DI.
|
|
13
|
+
|
|
14
|
+
## Services
|
|
15
|
+
|
|
16
|
+
A **service** is the most common way to share data and functionality across an application. It is a TypeScript class decorated with `@Injectable()`.
|
|
17
|
+
|
|
18
|
+
### Creating a Service
|
|
19
|
+
|
|
20
|
+
Use the `providedIn: 'root'` option in the `@Injectable` decorator to make the service a singleton available throughout the entire application. This is the recommended approach for most services.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import {Injectable} from '@angular/core';
|
|
24
|
+
|
|
25
|
+
@Injectable({
|
|
26
|
+
providedIn: 'root', // Makes this a singleton available everywhere
|
|
27
|
+
})
|
|
28
|
+
export class AnalyticsLogger {
|
|
29
|
+
trackEvent(category: string, value: string) {
|
|
30
|
+
console.log('Analytics event logged:', {category, value});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Common uses for services include:
|
|
36
|
+
|
|
37
|
+
- Data clients (API calls)
|
|
38
|
+
- State management
|
|
39
|
+
- Authentication and authorization
|
|
40
|
+
- Logging and error handling
|
|
41
|
+
- Utility functions
|
|
42
|
+
|
|
43
|
+
## Injecting Dependencies
|
|
44
|
+
|
|
45
|
+
Use Angular's `inject()` function to request dependencies.
|
|
46
|
+
|
|
47
|
+
### The `inject()` Function
|
|
48
|
+
|
|
49
|
+
You can use the `inject()` function to get an instance of a service (or any other provided token).
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import {Component, inject} from '@angular/core';
|
|
53
|
+
import {Router} from '@angular/router';
|
|
54
|
+
import {AnalyticsLogger} from './analytics-logger.service';
|
|
55
|
+
|
|
56
|
+
@Component({
|
|
57
|
+
selector: 'app-navbar',
|
|
58
|
+
template: `<a href="#" (click)="navigateToDetail($event)">Detail Page</a>`,
|
|
59
|
+
})
|
|
60
|
+
export class Navbar {
|
|
61
|
+
// Injecting dependencies using class field initializers
|
|
62
|
+
private router = inject(Router);
|
|
63
|
+
private analytics = inject(AnalyticsLogger);
|
|
64
|
+
|
|
65
|
+
navigateToDetail(event: Event) {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
this.analytics.trackEvent('navigation', '/details');
|
|
68
|
+
this.router.navigate(['/details']);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Where can `inject()` be used? (Injection Context)
|
|
74
|
+
|
|
75
|
+
You can call `inject()` in an **injection context**. The most common injection contexts are during the construction of a component, directive, or service.
|
|
76
|
+
|
|
77
|
+
Valid places to call `inject()`:
|
|
78
|
+
|
|
79
|
+
1. **Class field initializers** (Recommended)
|
|
80
|
+
2. **Constructor body**
|
|
81
|
+
3. **Route guards and resolvers** (which are executed in an injection context)
|
|
82
|
+
4. **Factory functions** used in providers
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import {Component, Directive, Injectable, inject, ElementRef} from '@angular/core';
|
|
86
|
+
import {HttpClient} from '@angular/common/http';
|
|
87
|
+
|
|
88
|
+
// 1. In a Component (Field Initializer & Constructor)
|
|
89
|
+
@Component({
|
|
90
|
+
/*...*/
|
|
91
|
+
})
|
|
92
|
+
export class Example {
|
|
93
|
+
private service1 = inject(MyService); // Valid field initializer
|
|
94
|
+
|
|
95
|
+
private service2: MyService;
|
|
96
|
+
constructor() {
|
|
97
|
+
this.service2 = inject(MyService); // Valid constructor body
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 2. In a Directive
|
|
102
|
+
@Directive({
|
|
103
|
+
/*...*/
|
|
104
|
+
})
|
|
105
|
+
export class MyDirective {
|
|
106
|
+
private element = inject(ElementRef); // Valid field initializer
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 3. In a Service
|
|
110
|
+
@Injectable({providedIn: 'root'})
|
|
111
|
+
export class MyService {
|
|
112
|
+
private http = inject(HttpClient); // Valid field initializer
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 4. In a Route Guard (Functional)
|
|
116
|
+
export const authGuard = () => {
|
|
117
|
+
const auth = inject(AuthService); // Valid route guard
|
|
118
|
+
return auth.isAuthenticated();
|
|
119
|
+
};
|
|
120
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# End-to-End (E2E) Testing
|
|
2
|
+
|
|
3
|
+
Use E2E tests to cover critical user journeys in a real browser. Prefer the framework already configured in the Angular workspace, such as Cypress or Playwright.
|
|
4
|
+
|
|
5
|
+
## Running E2E Tests
|
|
6
|
+
|
|
7
|
+
Check `package.json` and `angular.json` for the project-specific command. Common patterns include:
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
npm run e2e
|
|
11
|
+
pnpm e2e
|
|
12
|
+
ng e2e
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
When the app must be built or served first, use the existing project scripts instead of inventing a parallel test entrypoint.
|
|
16
|
+
|
|
17
|
+
## Test Structure
|
|
18
|
+
|
|
19
|
+
- Keep E2E specs close to the configured test framework, such as `cypress/e2e/` or `e2e/`.
|
|
20
|
+
- Put reusable login/setup helpers in the framework support directory.
|
|
21
|
+
- Keep fixtures explicit and small enough that each test can explain the user state it depends on.
|
|
22
|
+
|
|
23
|
+
### Cypress Example
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
describe('Login flow', () => {
|
|
27
|
+
it('redirects to dashboard on valid credentials', () => {
|
|
28
|
+
cy.visit('/login');
|
|
29
|
+
cy.get('[data-cy=email]').type('user@example.com');
|
|
30
|
+
cy.get('[data-cy=password]').type('password123');
|
|
31
|
+
cy.get('[data-cy=submit]').click();
|
|
32
|
+
cy.url().should('include', '/dashboard');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Playwright Example
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import {expect, test} from '@playwright/test';
|
|
41
|
+
|
|
42
|
+
test('redirects to dashboard on valid credentials', async ({page}) => {
|
|
43
|
+
await page.goto('/login');
|
|
44
|
+
await page.getByLabel('Email').fill('user@example.com');
|
|
45
|
+
await page.getByLabel('Password').fill('password123');
|
|
46
|
+
await page.getByRole('button', {name: 'Sign in'}).click();
|
|
47
|
+
await expect(page).toHaveURL(/dashboard/);
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Best Practices
|
|
52
|
+
|
|
53
|
+
- Prefer accessible locators (`getByRole`, `getByLabel`) or stable `data-*` attributes.
|
|
54
|
+
- Avoid selectors that depend on CSS classes, DOM depth, or incidental text.
|
|
55
|
+
- Wait for specific UI states, routes, or network responses instead of arbitrary sleeps.
|
|
56
|
+
- Keep smoke tests short and reserve full workflow coverage for the highest-value paths.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Side Effects with `effect` and `afterRenderEffect`
|
|
2
|
+
|
|
3
|
+
In Angular, an **effect** is an operation that runs whenever one or more signal values it tracks change.
|
|
4
|
+
|
|
5
|
+
## When to use `effect`
|
|
6
|
+
|
|
7
|
+
Effects are intended for syncing signal state to imperative, non-signal APIs.
|
|
8
|
+
|
|
9
|
+
**Valid Use Cases:**
|
|
10
|
+
|
|
11
|
+
- Logging analytics.
|
|
12
|
+
- Syncing state to `localStorage` or `sessionStorage`.
|
|
13
|
+
- Performing custom rendering to a `<canvas>` or 3rd-party charting library.
|
|
14
|
+
|
|
15
|
+
**CRITICAL RULE: DO NOT use effects to propagate state.**
|
|
16
|
+
If you find yourself using `.set()` or `.update()` on a signal _inside_ an effect to keep two signals in sync, you are making a mistake. This causes `ExpressionChangedAfterItHasBeenChecked` errors and infinite loops. **Always use `computed()` or `linkedSignal()` for state derivation.**
|
|
17
|
+
|
|
18
|
+
## Basic Usage
|
|
19
|
+
|
|
20
|
+
Effects execute asynchronously during the change detection process. They always run at least once.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Component, signal, effect } from '@angular/core';
|
|
24
|
+
|
|
25
|
+
@Component({...})
|
|
26
|
+
export class Example {
|
|
27
|
+
count = signal(0);
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
// Effect must be created in an injection context (e.g., a constructor)
|
|
31
|
+
effect((onCleanup) => {
|
|
32
|
+
console.log(`Count changed to ${this.count()}`);
|
|
33
|
+
|
|
34
|
+
const timer = setTimeout(() => console.log('Timer finished'), 1000);
|
|
35
|
+
|
|
36
|
+
// Cleanup function runs before the next execution, or when destroyed
|
|
37
|
+
onCleanup(() => clearTimeout(timer));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## DOM Manipulation with `afterRenderEffect`
|
|
44
|
+
|
|
45
|
+
Standard `effect` runs _before_ Angular updates the DOM. If you need to manually inspect or modify the DOM based on a signal change (e.g., integrating a 3rd party UI library), use `afterRenderEffect`.
|
|
46
|
+
|
|
47
|
+
`afterRenderEffect` runs after Angular has finished rendering the DOM.
|
|
48
|
+
|
|
49
|
+
### Render Phases
|
|
50
|
+
|
|
51
|
+
To prevent reflows (forced layout thrashing), `afterRenderEffect` forces you to divide your DOM reads and writes into specific phases.
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { Component, afterRenderEffect, viewChild, ElementRef } from '@angular/core';
|
|
55
|
+
|
|
56
|
+
@Component({...})
|
|
57
|
+
export class Chart {
|
|
58
|
+
canvas = viewChild.required<ElementRef>('canvas');
|
|
59
|
+
|
|
60
|
+
constructor() {
|
|
61
|
+
afterRenderEffect({
|
|
62
|
+
// 1. Read from the DOM
|
|
63
|
+
earlyRead: () => {
|
|
64
|
+
return this.canvas().nativeElement.getBoundingClientRect().width;
|
|
65
|
+
},
|
|
66
|
+
// 2. Write to the DOM (receives the result of the previous phase)
|
|
67
|
+
write: (width) => {
|
|
68
|
+
// NEVER read from the DOM in the write phase.
|
|
69
|
+
setupChart(this.canvas().nativeElement, width);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Available Phases (executed in this order):**
|
|
77
|
+
|
|
78
|
+
1. `earlyRead`
|
|
79
|
+
2. `write` (Never read here)
|
|
80
|
+
3. `mixedReadWrite` (Avoid if possible)
|
|
81
|
+
4. `read` (Never write here)
|
|
82
|
+
|
|
83
|
+
_Note: `afterRenderEffect` only runs on the client, never during Server-Side Rendering (SSR)._
|