@ngxtm/devkit 3.4.0 → 3.5.0
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/package.json +2 -1
- package/rules/README.md +141 -0
- package/rules/dart/best-practices/SKILL.md +23 -0
- package/rules/dart/language/SKILL.md +52 -0
- package/rules/dart/tooling/SKILL.md +43 -0
- package/rules/dotnet/aspnet-core/SKILL.md +92 -0
- package/rules/dotnet/aspnet-core/references/REFERENCE.md +335 -0
- package/rules/dotnet/best-practices/SKILL.md +101 -0
- package/rules/dotnet/best-practices/references/REFERENCE.md +256 -0
- package/rules/dotnet/blazor/SKILL.md +146 -0
- package/rules/dotnet/blazor/references/REFERENCE.md +392 -0
- package/rules/dotnet/language/SKILL.md +82 -0
- package/rules/dotnet/language/references/REFERENCE.md +222 -0
- package/rules/dotnet/patterns.rule.md +388 -0
- package/rules/dotnet/razor-pages/SKILL.md +124 -0
- package/rules/dotnet/razor-pages/references/REFERENCE.md +321 -0
- package/rules/dotnet/security/SKILL.md +89 -0
- package/rules/dotnet/security/references/REFERENCE.md +295 -0
- package/rules/dotnet/tooling/SKILL.md +92 -0
- package/rules/dotnet/tooling/references/REFERENCE.md +300 -0
- package/rules/flutter/auto-route-navigation/SKILL.md +43 -0
- package/rules/flutter/auto-route-navigation/references/REFERENCE.md +19 -0
- package/rules/flutter/auto-route-navigation/references/router-config.md +62 -0
- package/rules/flutter/bloc-state-management/SKILL.md +64 -0
- package/rules/flutter/bloc-state-management/references/REFERENCE.md +20 -0
- package/rules/flutter/bloc-state-management/references/auth-bloc-example.md +52 -0
- package/rules/flutter/bloc-state-management/references/equatable-usage.md +56 -0
- package/rules/flutter/bloc-state-management/references/property-based-state.md +68 -0
- package/rules/flutter/bloc.rule.md +76 -0
- package/rules/flutter/cicd/SKILL.md +48 -0
- package/rules/flutter/cicd/references/advanced-workflow.md +66 -0
- package/rules/flutter/cicd/references/fastlane.md +139 -0
- package/rules/flutter/cicd/references/github-actions.md +59 -0
- package/rules/flutter/dependency-injection/SKILL.md +42 -0
- package/rules/flutter/dependency-injection/references/REFERENCE.md +15 -0
- package/rules/flutter/dependency-injection/references/modules.md +37 -0
- package/rules/flutter/error-handling/SKILL.md +32 -0
- package/rules/flutter/error-handling/references/REFERENCE.md +19 -0
- package/rules/flutter/error-handling/references/error-mapping.md +31 -0
- package/rules/flutter/feature-based-clean-architecture/SKILL.md +46 -0
- package/rules/flutter/feature-based-clean-architecture/references/REFERENCE.md +14 -0
- package/rules/flutter/feature-based-clean-architecture/references/folder-structure.md +36 -0
- package/rules/flutter/getx-navigation/SKILL.md +70 -0
- package/rules/flutter/getx-navigation/references/app-pages.md +40 -0
- package/rules/flutter/getx-navigation/references/middleware-example.md +29 -0
- package/rules/flutter/getx-state-management/SKILL.md +76 -0
- package/rules/flutter/getx-state-management/references/binding-example.md +32 -0
- package/rules/flutter/getx-state-management/references/reactive-vs-simple.md +39 -0
- package/rules/flutter/go-router-navigation/SKILL.md +57 -0
- package/rules/flutter/idiomatic-flutter/SKILL.md +20 -0
- package/rules/flutter/layer-based-clean-architecture/SKILL.md +50 -0
- package/rules/flutter/layer-based-clean-architecture/references/REFERENCE.md +60 -0
- package/rules/flutter/layer-based-clean-architecture/references/repository-mapping.md +50 -0
- package/rules/flutter/localization/SKILL.md +50 -0
- package/rules/flutter/localization/references/REFERENCE.md +48 -0
- package/rules/flutter/localization/references/sheet-loader.md +33 -0
- package/rules/flutter/navigator-v1-navigation/SKILL.md +71 -0
- package/rules/flutter/navigator-v1-navigation/references/on-generate-route.md +48 -0
- package/rules/flutter/performance/SKILL.md +24 -0
- package/rules/flutter/retrofit-networking/SKILL.md +51 -0
- package/rules/flutter/retrofit-networking/references/REFERENCE.md +19 -0
- package/rules/flutter/retrofit-networking/references/token-refresh.md +40 -0
- package/rules/flutter/riverpod-state-management/SKILL.md +53 -0
- package/rules/flutter/riverpod-state-management/references/architecture.md +124 -0
- package/rules/flutter/riverpod-state-management/references/best-practices.md +89 -0
- package/rules/flutter/riverpod-state-management/references/testing.md +73 -0
- package/rules/flutter/riverpod.rule.md +78 -0
- package/rules/flutter/security/SKILL.md +33 -0
- package/rules/flutter/security/references/REFERENCE.md +15 -0
- package/rules/flutter/security/references/network-security.md +28 -0
- package/rules/flutter/testing/SKILL.md +44 -0
- package/rules/flutter/testing/references/REFERENCE.md +21 -0
- package/rules/flutter/testing/references/bloc-testing.md +38 -0
- package/rules/flutter/testing/references/integration-testing.md +128 -0
- package/rules/flutter/testing/references/robot-pattern.md +82 -0
- package/rules/flutter/testing/references/unit-testing.md +130 -0
- package/rules/flutter/testing/references/widget-testing.md +120 -0
- package/rules/flutter/widgets/SKILL.md +37 -0
- package/rules/golang/chi-router/SKILL.md +219 -0
- package/rules/golang/chi-router/references/REFERENCE.md +13 -0
- package/rules/golang/chi-router/references/routing-patterns.md +205 -0
- package/rules/golang/cobra-cli/SKILL.md +227 -0
- package/rules/golang/cobra-cli/references/REFERENCE.md +13 -0
- package/rules/golang/cobra-cli/references/command-patterns.md +224 -0
- package/rules/golang/core/SKILL.md +210 -0
- package/rules/golang/core/references/REFERENCE.md +14 -0
- package/rules/golang/core/references/concurrency-patterns.md +114 -0
- package/rules/golang/core/references/error-handling.md +87 -0
- package/rules/golang/echo-framework/SKILL.md +215 -0
- package/rules/golang/echo-framework/references/REFERENCE.md +14 -0
- package/rules/golang/echo-framework/references/middleware-patterns.md +141 -0
- package/rules/golang/echo-framework/references/routing-patterns.md +140 -0
- package/rules/golang/ent-orm/SKILL.md +239 -0
- package/rules/golang/ent-orm/references/REFERENCE.md +13 -0
- package/rules/golang/ent-orm/references/schema-patterns.md +255 -0
- package/rules/golang/fiber-framework/SKILL.md +196 -0
- package/rules/golang/fiber-framework/references/REFERENCE.md +13 -0
- package/rules/golang/fiber-framework/references/routing-patterns.md +191 -0
- package/rules/golang/gin-framework/SKILL.md +205 -0
- package/rules/golang/gin-framework/references/REFERENCE.md +14 -0
- package/rules/golang/gin-framework/references/middleware-patterns.md +119 -0
- package/rules/golang/gorm-orm/SKILL.md +196 -0
- package/rules/golang/gorm-orm/references/REFERENCE.md +14 -0
- package/rules/golang/gorm-orm/references/model-definitions.md +167 -0
- package/rules/golang/gorm-orm/references/query-patterns.md +161 -0
- package/rules/golang/grpc/SKILL.md +231 -0
- package/rules/golang/grpc/references/REFERENCE.md +13 -0
- package/rules/golang/grpc/references/service-patterns.md +276 -0
- package/rules/golang/testify/SKILL.md +239 -0
- package/rules/golang/testify/references/REFERENCE.md +13 -0
- package/rules/golang/testify/references/assert-patterns.md +170 -0
- package/rules/golang/validator/SKILL.md +234 -0
- package/rules/golang/validator/references/REFERENCE.md +13 -0
- package/rules/golang/validator/references/validation-tags.md +211 -0
- package/rules/golang/viper-config/SKILL.md +244 -0
- package/rules/golang/viper-config/references/REFERENCE.md +13 -0
- package/rules/golang/viper-config/references/config-loading.md +181 -0
- package/rules/golang/wire-di/SKILL.md +243 -0
- package/rules/golang/wire-di/references/REFERENCE.md +13 -0
- package/rules/golang/wire-di/references/provider-patterns.md +193 -0
- package/rules/golang/zap-logging/SKILL.md +203 -0
- package/rules/golang/zap-logging/references/REFERENCE.md +13 -0
- package/rules/golang/zap-logging/references/logger-config.md +165 -0
- package/rules/java/build-gradle/SKILL.md +92 -0
- package/rules/java/build-gradle/references/REFERENCE.md +14 -0
- package/rules/java/build-gradle/references/kotlin-dsl.md +118 -0
- package/rules/java/build-gradle/references/task-configuration.md +132 -0
- package/rules/java/build-maven/SKILL.md +86 -0
- package/rules/java/build-maven/references/REFERENCE.md +14 -0
- package/rules/java/build-maven/references/dependency-management.md +111 -0
- package/rules/java/build-maven/references/lifecycle-phases.md +114 -0
- package/rules/java/graalvm-native/SKILL.md +105 -0
- package/rules/java/graalvm-native/references/REFERENCE.md +12 -0
- package/rules/java/java-collections-streams/SKILL.md +148 -0
- package/rules/java/java-collections-streams/references/REFERENCE.md +15 -0
- package/rules/java/java-collections-streams/references/collectors-patterns.md +178 -0
- package/rules/java/java-collections-streams/references/stream-pipelines.md +165 -0
- package/rules/java/java-concurrency/SKILL.md +187 -0
- package/rules/java/java-concurrency/references/REFERENCE.md +17 -0
- package/rules/java/java-concurrency/references/completable-future.md +165 -0
- package/rules/java/java-concurrency/references/executor-patterns.md +176 -0
- package/rules/java/java-concurrency/references/virtual-threads.md +190 -0
- package/rules/java/java-core-language/SKILL.md +121 -0
- package/rules/java/java-core-language/references/REFERENCE.md +15 -0
- package/rules/java/java-core-language/references/jvm-memory-model.md +160 -0
- package/rules/java/java-core-language/references/modern-java-features.md +168 -0
- package/rules/java/java-project-structure/SKILL.md +195 -0
- package/rules/java/java-project-structure/references/REFERENCE.md +15 -0
- package/rules/java/java-project-structure/references/maven-project-layout.md +199 -0
- package/rules/java/java-project-structure/references/module-system.md +159 -0
- package/rules/java/micronaut-core/SKILL.md +99 -0
- package/rules/java/micronaut-core/references/REFERENCE.md +12 -0
- package/rules/java/micronaut-reactive/SKILL.md +68 -0
- package/rules/java/micronaut-reactive/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-core/SKILL.md +85 -0
- package/rules/java/quarkus-core/references/REFERENCE.md +12 -0
- package/rules/java/quarkus-reactive/SKILL.md +67 -0
- package/rules/java/quarkus-reactive/references/REFERENCE.md +12 -0
- package/rules/java/spring-batch/SKILL.md +102 -0
- package/rules/java/spring-batch/references/REFERENCE.md +12 -0
- package/rules/java/spring-boot-architecture/SKILL.md +206 -0
- package/rules/java/spring-boot-architecture/references/REFERENCE.md +15 -0
- package/rules/java/spring-boot-architecture/references/auto-configuration.md +158 -0
- package/rules/java/spring-boot-architecture/references/configuration-properties.md +202 -0
- package/rules/java/spring-boot-web/SKILL.md +217 -0
- package/rules/java/spring-boot-web/references/REFERENCE.md +17 -0
- package/rules/java/spring-cloud/SKILL.md +109 -0
- package/rules/java/spring-cloud/references/REFERENCE.md +13 -0
- package/rules/java/spring-data-jpa/SKILL.md +241 -0
- package/rules/java/spring-data-jpa/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/SKILL.md +161 -0
- package/rules/java/spring-security/references/REFERENCE.md +16 -0
- package/rules/java/spring-security/references/jwt-auth-flow.md +213 -0
- package/rules/java/testing-junit-mockito/SKILL.md +135 -0
- package/rules/java/testing-junit-mockito/references/REFERENCE.md +15 -0
- package/rules/java/testing-junit-mockito/references/junit5-patterns.md +159 -0
- package/rules/java/testing-junit-mockito/references/mockito-patterns.md +148 -0
- package/rules/java/testing-junit-mockito/references/spring-boot-testing.md +152 -0
- package/rules/javascript/best-practices/SKILL.md +64 -0
- package/rules/javascript/best-practices/references/REFERENCE.md +91 -0
- package/rules/javascript/language/SKILL.md +71 -0
- package/rules/javascript/language/references/REFERENCE.md +106 -0
- package/rules/javascript/tooling/SKILL.md +60 -0
- package/rules/javascript/tooling/references/REFERENCE.md +107 -0
- package/rules/metadata.json +54 -0
- package/rules/nestjs/api-standards/SKILL.md +47 -0
- package/rules/nestjs/api-standards/references/pagination-wrapper.md +87 -0
- package/rules/nestjs/architecture/SKILL.md +68 -0
- package/rules/nestjs/architecture/references/dynamic-module.md +53 -0
- package/rules/nestjs/caching/SKILL.md +51 -0
- package/rules/nestjs/caching/references/REFERENCE.md +13 -0
- package/rules/nestjs/caching/references/cache-patterns.md +183 -0
- package/rules/nestjs/configuration/SKILL.md +41 -0
- package/rules/nestjs/configuration/references/REFERENCE.md +13 -0
- package/rules/nestjs/configuration/references/config-patterns.md +184 -0
- package/rules/nestjs/controllers-services/SKILL.md +63 -0
- package/rules/nestjs/controllers-services/references/REFERENCE.md +14 -0
- package/rules/nestjs/controllers-services/references/controller-patterns.md +119 -0
- package/rules/nestjs/controllers-services/references/service-patterns.md +129 -0
- package/rules/nestjs/database/SKILL.md +102 -0
- package/rules/nestjs/database/references/REFERENCE.md +14 -0
- package/rules/nestjs/database/references/typeorm-patterns.md +156 -0
- package/rules/nestjs/deployment/SKILL.md +36 -0
- package/rules/nestjs/deployment/references/REFERENCE.md +13 -0
- package/rules/nestjs/deployment/references/deployment-patterns.md +140 -0
- package/rules/nestjs/documentation/SKILL.md +64 -0
- package/rules/nestjs/documentation/references/REFERENCE.md +13 -0
- package/rules/nestjs/documentation/references/swagger-patterns.md +139 -0
- package/rules/nestjs/error-handling/SKILL.md +55 -0
- package/rules/nestjs/error-handling/references/REFERENCE.md +13 -0
- package/rules/nestjs/error-handling/references/exception-filters.md +152 -0
- package/rules/nestjs/file-uploads/SKILL.md +35 -0
- package/rules/nestjs/file-uploads/references/REFERENCE.md +13 -0
- package/rules/nestjs/file-uploads/references/upload-patterns.md +125 -0
- package/rules/nestjs/observability/SKILL.md +39 -0
- package/rules/nestjs/observability/references/REFERENCE.md +13 -0
- package/rules/nestjs/observability/references/logging-metrics.md +175 -0
- package/rules/nestjs/performance/SKILL.md +60 -0
- package/rules/nestjs/performance/references/REFERENCE.md +13 -0
- package/rules/nestjs/performance/references/performance-patterns.md +107 -0
- package/rules/nestjs/real-time/SKILL.md +45 -0
- package/rules/nestjs/real-time/references/REFERENCE.md +13 -0
- package/rules/nestjs/real-time/references/websocket-patterns.md +121 -0
- package/rules/nestjs/scheduling/SKILL.md +39 -0
- package/rules/nestjs/scheduling/references/REFERENCE.md +13 -0
- package/rules/nestjs/scheduling/references/scheduling-patterns.md +137 -0
- package/rules/nestjs/search/SKILL.md +41 -0
- package/rules/nestjs/search/references/REFERENCE.md +13 -0
- package/rules/nestjs/search/references/search-patterns.md +137 -0
- package/rules/nestjs/security/SKILL.md +87 -0
- package/rules/nestjs/security/references/REFERENCE.md +14 -0
- package/rules/nestjs/security/references/authentication.md +151 -0
- package/rules/nestjs/testing/SKILL.md +40 -0
- package/rules/nestjs/testing/references/REFERENCE.md +14 -0
- package/rules/nestjs/testing/references/unit-testing.md +179 -0
- package/rules/nestjs/transport/SKILL.md +45 -0
- package/rules/nestjs/transport/references/REFERENCE.md +13 -0
- package/rules/nestjs/transport/references/microservices-patterns.md +170 -0
- package/rules/nextjs/app-router/SKILL.md +46 -0
- package/rules/nextjs/app-router/references/REFERENCE.md +14 -0
- package/rules/nextjs/app-router/references/routing-patterns.md +182 -0
- package/rules/nextjs/architecture/SKILL.md +44 -0
- package/rules/nextjs/architecture/references/fsd-structure.md +77 -0
- package/rules/nextjs/authentication/SKILL.md +29 -0
- package/rules/nextjs/authentication/references/auth-implementation.md +73 -0
- package/rules/nextjs/caching/SKILL.md +66 -0
- package/rules/nextjs/caching/references/REFERENCE.md +13 -0
- package/rules/nextjs/caching/references/cache-strategies.md +168 -0
- package/rules/nextjs/data-access-layer/SKILL.md +33 -0
- package/rules/nextjs/data-access-layer/references/patterns.md +66 -0
- package/rules/nextjs/data-fetching/SKILL.md +59 -0
- package/rules/nextjs/data-fetching/references/REFERENCE.md +13 -0
- package/rules/nextjs/data-fetching/references/fetch-patterns.md +160 -0
- package/rules/nextjs/internationalization/SKILL.md +105 -0
- package/rules/nextjs/internationalization/references/REFERENCE.md +13 -0
- package/rules/nextjs/internationalization/references/i18n-patterns.md +180 -0
- package/rules/nextjs/optimization/SKILL.md +64 -0
- package/rules/nextjs/optimization/references/REFERENCE.md +13 -0
- package/rules/nextjs/optimization/references/optimization-patterns.md +190 -0
- package/rules/nextjs/rendering/SKILL.md +91 -0
- package/rules/nextjs/rendering/references/REFERENCE.md +13 -0
- package/rules/nextjs/rendering/references/rendering-modes.md +163 -0
- package/rules/nextjs/server-actions/SKILL.md +46 -0
- package/rules/nextjs/server-actions/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-actions/references/action-patterns.md +188 -0
- package/rules/nextjs/server-components/SKILL.md +52 -0
- package/rules/nextjs/server-components/references/REFERENCE.md +13 -0
- package/rules/nextjs/server-components/references/component-patterns.md +175 -0
- package/rules/nextjs/state-management/SKILL.md +73 -0
- package/rules/nextjs/state-management/references/REFERENCE.md +13 -0
- package/rules/nextjs/state-management/references/state-patterns.md +218 -0
- package/rules/nextjs/styling/SKILL.md +31 -0
- package/rules/nextjs/styling/references/implementation.md +56 -0
- package/rules/react/component-patterns/SKILL.md +66 -0
- package/rules/react/component-patterns/references/REFERENCE.md +126 -0
- package/rules/react/hooks/SKILL.md +60 -0
- package/rules/react/hooks/references/REFERENCE.md +132 -0
- package/rules/react/hooks.rule.md +79 -0
- package/rules/react/performance/SKILL.md +69 -0
- package/rules/react/performance/references/REFERENCE.md +143 -0
- package/rules/react/security/SKILL.md +46 -0
- package/rules/react/security/references/REFERENCE.md +170 -0
- package/rules/react/state-management/SKILL.md +56 -0
- package/rules/react/state-management/references/REFERENCE.md +137 -0
- package/rules/react/testing/SKILL.md +45 -0
- package/rules/react/testing/references/REFERENCE.md +149 -0
- package/rules/react/tooling/SKILL.md +39 -0
- package/rules/react/typescript/SKILL.md +53 -0
- package/rules/rust/actix-web/SKILL.md +160 -0
- package/rules/rust/actix-web/references/REFERENCE.md +13 -0
- package/rules/rust/actix-web/references/handler-patterns.md +198 -0
- package/rules/rust/async-graphql/SKILL.md +228 -0
- package/rules/rust/async-graphql/references/REFERENCE.md +13 -0
- package/rules/rust/async-graphql/references/schema-patterns.md +215 -0
- package/rules/rust/axum/SKILL.md +161 -0
- package/rules/rust/axum/references/REFERENCE.md +14 -0
- package/rules/rust/axum/references/handler-patterns.md +97 -0
- package/rules/rust/bevy/SKILL.md +206 -0
- package/rules/rust/bevy/references/REFERENCE.md +13 -0
- package/rules/rust/bevy/references/ecs-patterns.md +226 -0
- package/rules/rust/clap/SKILL.md +217 -0
- package/rules/rust/clap/references/REFERENCE.md +13 -0
- package/rules/rust/clap/references/derive-patterns.md +205 -0
- package/rules/rust/core/SKILL.md +154 -0
- package/rules/rust/core/references/REFERENCE.md +14 -0
- package/rules/rust/core/references/error-handling.md +92 -0
- package/rules/rust/diesel-orm/SKILL.md +176 -0
- package/rules/rust/diesel-orm/references/REFERENCE.md +13 -0
- package/rules/rust/diesel-orm/references/schema-patterns.md +206 -0
- package/rules/rust/rocket/SKILL.md +182 -0
- package/rules/rust/rocket/references/REFERENCE.md +13 -0
- package/rules/rust/rocket/references/handler-patterns.md +209 -0
- package/rules/rust/sea-orm/SKILL.md +230 -0
- package/rules/rust/sea-orm/references/REFERENCE.md +13 -0
- package/rules/rust/sea-orm/references/entity-patterns.md +221 -0
- package/rules/rust/serde-serialization/SKILL.md +150 -0
- package/rules/rust/serde-serialization/references/REFERENCE.md +13 -0
- package/rules/rust/serde-serialization/references/serialization-patterns.md +199 -0
- package/rules/rust/sqlx-database/SKILL.md +140 -0
- package/rules/rust/sqlx-database/references/REFERENCE.md +13 -0
- package/rules/rust/sqlx-database/references/query-patterns.md +210 -0
- package/rules/rust/tauri/SKILL.md +180 -0
- package/rules/rust/tauri/references/REFERENCE.md +13 -0
- package/rules/rust/tauri/references/command-patterns.md +209 -0
- package/rules/rust/tokio-runtime/SKILL.md +167 -0
- package/rules/rust/tokio-runtime/references/REFERENCE.md +14 -0
- package/rules/rust/tokio-runtime/references/async-patterns.md +137 -0
- package/rules/rust/tokio-runtime/references/synchronization.md +152 -0
- package/rules/rust/tonic/SKILL.md +231 -0
- package/rules/rust/tonic/references/REFERENCE.md +13 -0
- package/rules/rust/tonic/references/service-patterns.md +213 -0
- package/rules/rust/tracing/SKILL.md +214 -0
- package/rules/rust/tracing/references/REFERENCE.md +13 -0
- package/rules/rust/tracing/references/instrumentation.md +187 -0
- package/rules/typescript/best-practices/SKILL.md +108 -0
- package/rules/typescript/best-practices/references/REFERENCE.md +68 -0
- package/rules/typescript/language/SKILL.md +72 -0
- package/rules/typescript/language/references/REFERENCE.md +67 -0
- package/rules/typescript/patterns.rule.md +85 -0
- package/rules/typescript/security/SKILL.md +59 -0
- package/rules/typescript/security/references/REFERENCE.md +113 -0
- package/rules/typescript/tooling/SKILL.md +52 -0
- package/rules/typescript/tooling/references/REFERENCE.md +110 -0
- package/skills/learn/SKILL.md +476 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Flutter Networking (Retrofit & Dio)
|
|
3
|
+
description: HTTP networking standards using Dio and Retrofit with Auth interceptors.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [networking, retrofit, dio]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/data_sources/**', '**/api/**']
|
|
8
|
+
keywords: [Retrofit, Dio, RestClient, GET, POST, Interceptor, refreshing]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Retrofit & Dio Networking
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Type-safe REST API communication using `Dio` and `Retrofit`.
|
|
16
|
+
|
|
17
|
+
## Structure
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
infrastructure/
|
|
21
|
+
├── data_sources/
|
|
22
|
+
│ ├── remote/ # Retrofit abstract classes
|
|
23
|
+
│ └── local/ # Cache/Storage
|
|
24
|
+
└── network/
|
|
25
|
+
├── dio_client.dart # Custom Dio setup
|
|
26
|
+
└── interceptors/ # Auth, Logging, Cache
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Implementation Guidelines
|
|
30
|
+
|
|
31
|
+
- **Retrofit Clients**: Define abstract classes with `@RestApi()`. Use standard HTTP annotations (`@GET`, `@POST`).
|
|
32
|
+
- **DTOs (Data Transfer Objects)**: Use `@freezed` and `json_serializable` for all response/request bodies.
|
|
33
|
+
- **Mapping**: Data sources MUST map DTOs to Domain Entities (e.g., `userDto.toDomain()`).
|
|
34
|
+
- **AuthInterceptor**: Logic for `Authorization: Bearer <token>` injection in `onRequest`.
|
|
35
|
+
- **Token Refresh**: Handle `401 Unauthorized` in `onError` by locking Dio, refreshing, and retrying.
|
|
36
|
+
- **Failures**: Map `DioException` to custom `Failure` objects (ServerFailure, NetworkFailure).
|
|
37
|
+
|
|
38
|
+
## Anti-Patterns
|
|
39
|
+
|
|
40
|
+
- **No Manual JSON Parsing**: Do not use `jsonDecode(response.body)`; use Retrofit's generated mappers.
|
|
41
|
+
- **No Global Dio**: Do not use a static global Dio instance; use dependency injection.
|
|
42
|
+
- **No Try-Catch in API**: Do not put `try-catch` inside the Retrofit interface methods.
|
|
43
|
+
|
|
44
|
+
## Reference & Examples
|
|
45
|
+
|
|
46
|
+
For RestClient definitions and Auth Interceptor implementation:
|
|
47
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
48
|
+
|
|
49
|
+
## Related Topics
|
|
50
|
+
|
|
51
|
+
feature-based-clean-architecture | error-handling
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Retrofit & Dio Reference
|
|
2
|
+
|
|
3
|
+
Standards for API communication and networking logic.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**RestClient Setup**](client-definition.md) - Standard Retrofit interface examples.
|
|
8
|
+
- [**Auth Interceptors**](auth-interceptor.md) - Handling Bearer tokens and Auth headers.
|
|
9
|
+
- [**Token Refresh Logic**](token-refresh.md) - The 401 Lock-Refresh-Retry pattern.
|
|
10
|
+
|
|
11
|
+
## **Quick Definition**
|
|
12
|
+
|
|
13
|
+
```dart
|
|
14
|
+
@RestApi()
|
|
15
|
+
abstract class ApiClient {
|
|
16
|
+
@GET("/items")
|
|
17
|
+
Future<List<ItemDto>> getItems(@Query("limit") int limit);
|
|
18
|
+
}
|
|
19
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Token Refresh Pattern
|
|
2
|
+
|
|
3
|
+
When a `401 Unauthorized` error occurs, the networking layer should handle the refresh cycle transparently.
|
|
4
|
+
|
|
5
|
+
## **Implementation Flow (Dio Interceptor)**
|
|
6
|
+
|
|
7
|
+
```dart
|
|
8
|
+
class AuthInterceptor extends QueuedInterceptorsWrapper {
|
|
9
|
+
final Dio dio;
|
|
10
|
+
final SecureStorage storage;
|
|
11
|
+
|
|
12
|
+
AuthInterceptor(this.dio, this.storage);
|
|
13
|
+
|
|
14
|
+
@override
|
|
15
|
+
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
|
16
|
+
if (err.response?.statusCode == 401) {
|
|
17
|
+
// 1. Refresh the token
|
|
18
|
+
final newToken = await _performRefresh();
|
|
19
|
+
|
|
20
|
+
if (newToken != null) {
|
|
21
|
+
// 2. Retry the original request with new token
|
|
22
|
+
final options = err.requestOptions;
|
|
23
|
+
options.headers['Authorization'] = 'Bearer $newToken';
|
|
24
|
+
|
|
25
|
+
final response = await dio.fetch(options);
|
|
26
|
+
return handler.resolve(response);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return handler.next(err);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Future<String?> _performRefresh() async {
|
|
33
|
+
// Logic to call refresh endpoint and update storage
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## **Why QueuedInterceptorsWrapper?**
|
|
39
|
+
|
|
40
|
+
Using `QueuedInterceptorsWrapper` ensures that if multiple requests trigger a 401 at the same time, they are queued while the first one performs the token refresh, preventing multiple redundant refresh calls.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Flutter Riverpod State Management
|
|
3
|
+
description: Reactive state management using Riverpod 2.0 with code generation.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [state-management, riverpod, dependency-injection, reactive]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**_provider.dart', '**_notifier.dart']
|
|
8
|
+
keywords: [riverpod, ProviderScope, ConsumerWidget, Notifier, AsyncValue, ref.watch, "@riverpod"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Riverpod State Management
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Type-safe, compile-time safe reactive state management using `riverpod` and `riverpod_generator`.
|
|
16
|
+
|
|
17
|
+
## Structure
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
lib/
|
|
21
|
+
├── providers/ # Global providers and services
|
|
22
|
+
└── features/
|
|
23
|
+
└── user/
|
|
24
|
+
├── providers/ # Feature-specific providers
|
|
25
|
+
└── models/ # @freezed domain models
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Implementation Guidelines
|
|
29
|
+
|
|
30
|
+
- **Generator First**: Use `@riverpod` annotations and `riverpod_generator`. Avoid manual `Provider` definitions.
|
|
31
|
+
- **Immutability**: Maintain immutable states. Use `Freezed` for all state models.
|
|
32
|
+
- **Provider Methods**:
|
|
33
|
+
- `ref.watch()`: Use inside `build()` to rebuild on changes.
|
|
34
|
+
- `ref.listen()`: Use for side-effects (navigation, dialogs).
|
|
35
|
+
- `ref.read()`: Use ONLY in callbacks (onPressed).
|
|
36
|
+
- **Asynchronous Data**: Use `AsyncNotifier` for complex async logic. Access data via `.when()` or `AsyncValue` pattern-matching.
|
|
37
|
+
- **Architecture**: Enforce 3-layer separation (Data, Domain, Presentation).
|
|
38
|
+
- **Linting**: Enable `riverpod_lint` and `custom_lint` for dependency cycle detection.
|
|
39
|
+
|
|
40
|
+
## Anti-Patterns
|
|
41
|
+
|
|
42
|
+
- **Building Inside Providers**: Don't perform side-effects inside provider initialization.
|
|
43
|
+
- **Context Access**: Never pass `BuildContext` into a Notifier/Provider.
|
|
44
|
+
- **Dynamic Providers**: Avoid local provider instantiation; keep them global.
|
|
45
|
+
|
|
46
|
+
## Reference & Examples
|
|
47
|
+
|
|
48
|
+
For architecture details, best practices, and testing overrides:
|
|
49
|
+
See [references/architecture.md](references/architecture.md), [references/best-practices.md](references/best-practices.md), and [references/testing.md](references/testing.md).
|
|
50
|
+
|
|
51
|
+
## Related Topics
|
|
52
|
+
|
|
53
|
+
feature-based-clean-architecture | dependency-injection | testing
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Architecture & Layers
|
|
2
|
+
|
|
3
|
+
## 1. Data Layer: Repository Interface & Providers
|
|
4
|
+
|
|
5
|
+
Always separate interface from implementation to enable easy mocking.
|
|
6
|
+
|
|
7
|
+
```dart
|
|
8
|
+
// domain/repository/user_repository.dart
|
|
9
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
10
|
+
import '../../data/repository/api_user_repository.dart';
|
|
11
|
+
import '../models/user.dart';
|
|
12
|
+
|
|
13
|
+
part 'user_repository.g.dart';
|
|
14
|
+
|
|
15
|
+
// 1. Define the Provider returning the INTERFACE
|
|
16
|
+
@riverpod
|
|
17
|
+
UserRepository userRepository(UserRepositoryRef ref) {
|
|
18
|
+
// Return the specific implementation here.
|
|
19
|
+
// Can be swapped for MockUserRepository based on environment flags.
|
|
20
|
+
return ApiUserRepository(ref.watch(apiClientProvider));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 2. Define the Interface
|
|
24
|
+
abstract interface class UserRepository {
|
|
25
|
+
Future<List<User>> getAllUsers();
|
|
26
|
+
Future<void> deleteUser(String id);
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```dart
|
|
31
|
+
// data/repository/api_user_repository.dart
|
|
32
|
+
class ApiUserRepository implements UserRepository {
|
|
33
|
+
final UserApiClient _client;
|
|
34
|
+
|
|
35
|
+
ApiUserRepository(this._client);
|
|
36
|
+
|
|
37
|
+
@override
|
|
38
|
+
Future<List<User>> getAllUsers() async {
|
|
39
|
+
return _client.fetchUsers();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 2. Presentation Layer: AsyncNotifier Controller
|
|
45
|
+
|
|
46
|
+
Use `AsyncNotifier` (via `@riverpod` class) to handle loading/error/data states naturally.
|
|
47
|
+
|
|
48
|
+
```dart
|
|
49
|
+
// features/users/user_controller.dart
|
|
50
|
+
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
51
|
+
import '../../domain/repository/user_repository.dart';
|
|
52
|
+
import '../../domain/models/user.dart';
|
|
53
|
+
|
|
54
|
+
part 'user_controller.g.dart';
|
|
55
|
+
|
|
56
|
+
@riverpod
|
|
57
|
+
class UserController extends _$UserController {
|
|
58
|
+
@override
|
|
59
|
+
FutureOr<List<User>> build() async {
|
|
60
|
+
// 1. Fetch initial data
|
|
61
|
+
return ref.watch(userRepositoryProvider).getAllUsers();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 2. Mutation Methods
|
|
65
|
+
Future<void> deleteUser(String id) async {
|
|
66
|
+
// Set loading state (optional, for optimisic UI usually prefer local)
|
|
67
|
+
// state = const AsyncLoading();
|
|
68
|
+
|
|
69
|
+
// Perform action
|
|
70
|
+
state = await AsyncValue.guard(() async {
|
|
71
|
+
await ref.read(userRepositoryProvider).deleteUser(id);
|
|
72
|
+
// Refresh logic:
|
|
73
|
+
// Option A: Refetch everything
|
|
74
|
+
return ref.refresh(userRepositoryProvider).getAllUsers();
|
|
75
|
+
|
|
76
|
+
// Option B: Optimistic Update (Better performance)
|
|
77
|
+
// final currentList = state.requireValue;
|
|
78
|
+
// return currentList.where((u) => u.id != id).toList();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 3. UI Layer: ConsumerWidget
|
|
85
|
+
|
|
86
|
+
Handle all 3 states (`data`, `loading`, `error`) using `.when`.
|
|
87
|
+
|
|
88
|
+
```dart
|
|
89
|
+
// features/users/user_list_screen.dart
|
|
90
|
+
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
91
|
+
|
|
92
|
+
class UserListScreen extends ConsumerWidget {
|
|
93
|
+
const UserListScreen({super.key});
|
|
94
|
+
|
|
95
|
+
@override
|
|
96
|
+
Widget build(BuildContext context, WidgetRef ref) {
|
|
97
|
+
// 1. Watch the Notifier Provider
|
|
98
|
+
final state = ref.watch(userControllerProvider);
|
|
99
|
+
|
|
100
|
+
return Scaffold(
|
|
101
|
+
body: state.when(
|
|
102
|
+
data: (users) => ListView.builder(
|
|
103
|
+
itemCount: users.length,
|
|
104
|
+
itemBuilder: (ctx, index) {
|
|
105
|
+
final user = users[index];
|
|
106
|
+
return ListTile(
|
|
107
|
+
title: Text(user.name),
|
|
108
|
+
// 2. Call mutation methods via .read()
|
|
109
|
+
trailing: IconButton(
|
|
110
|
+
icon: const Icon(Icons.delete),
|
|
111
|
+
onPressed: () {
|
|
112
|
+
ref.read(userControllerProvider.notifier).deleteUser(user.id);
|
|
113
|
+
},
|
|
114
|
+
),
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
),
|
|
118
|
+
loading: () => const Center(child: CircularProgressIndicator()),
|
|
119
|
+
error: (err, st) => Center(child: Text('Error: $err')),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Best Practices & DCM Rules
|
|
2
|
+
|
|
3
|
+
## Code Generation (`riverpod_generator`)
|
|
4
|
+
|
|
5
|
+
Always use code generation. It prevents syntax errors and handles "family" parameters automatically.
|
|
6
|
+
|
|
7
|
+
**❌ Bad (Legacy)**
|
|
8
|
+
|
|
9
|
+
```dart
|
|
10
|
+
final myProvider = Provider<String>((ref) => 'Hello'); // Manual typing, error prone
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**✅ Good (Generated)**
|
|
14
|
+
|
|
15
|
+
```dart
|
|
16
|
+
@riverpod
|
|
17
|
+
String my(MyRef ref) => 'Hello'; // Type-safe, auto-disposal by default
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Immutability & State Updates
|
|
21
|
+
|
|
22
|
+
Riverpod relies on strict object equality (`==`) to detect changes.
|
|
23
|
+
|
|
24
|
+
**❌ Bad (Mutation)**
|
|
25
|
+
|
|
26
|
+
```dart
|
|
27
|
+
state.add(newItem); // Same reference, listeners won't fire
|
|
28
|
+
state = state;
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**✅ Good (New Reference)**
|
|
32
|
+
|
|
33
|
+
```dart
|
|
34
|
+
state = [...state, newItem]; // New list, new reference
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## DCM & Linter Rules (`riverpod_lint`)
|
|
38
|
+
|
|
39
|
+
Enable strict rules in `analysis_options.yaml` via `custom_lint`.
|
|
40
|
+
|
|
41
|
+
### 1. `avoid-ref-read-inside-build`
|
|
42
|
+
|
|
43
|
+
**Rule**: Never use `ref.read` inside the `build()` method. It causes bugs where widgets don't update on change.
|
|
44
|
+
**Correct**: Use `ref.watch`.
|
|
45
|
+
|
|
46
|
+
### 2. `avoid-calling-notifier-members-inside-build`
|
|
47
|
+
|
|
48
|
+
**Rule**: Do not trigger side effects (API calls, internal mutations) inside `build`.
|
|
49
|
+
**Correct**: Use `build()` purely for initialization. Trigger actions via user interaction (onPressed) or `useEffect` (flutter_hooks).
|
|
50
|
+
|
|
51
|
+
### 3. `dispose-provided-instances`
|
|
52
|
+
|
|
53
|
+
**Rule**: If a provider creates a `ChangeNotifier` or stream controller, make sure it is disposed.
|
|
54
|
+
**Correct**:
|
|
55
|
+
|
|
56
|
+
```dart
|
|
57
|
+
@riverpod
|
|
58
|
+
StreamController myController(Ref ref) {
|
|
59
|
+
final controller = StreamController();
|
|
60
|
+
ref.onDispose(controller.close); // ✅ Register disposal
|
|
61
|
+
return controller;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 4. `use-ref-and-state-synchronously`
|
|
66
|
+
|
|
67
|
+
**Rule**: Don't use `ref` or setter `state` after an `await` without checking if the provider is still active.
|
|
68
|
+
**Context**: If a provider is disposed (e.g. user leaves screen) while an async task is running, setting state will throw.
|
|
69
|
+
|
|
70
|
+
**✅ Good**:
|
|
71
|
+
|
|
72
|
+
```dart
|
|
73
|
+
final result = await repo.fetch();
|
|
74
|
+
if (ref.context.mounted) { // Or simply rely on `AsyncValue.guard` which handles this somewhat safely
|
|
75
|
+
state = AsyncData(result);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## `keepAlive` Strategy
|
|
80
|
+
|
|
81
|
+
By default, auto-generated providers are `autoDispose`. This is good for memory but bad for caching.
|
|
82
|
+
|
|
83
|
+
- **Use `keepAlive: true`** for global data (User Session, App Config).
|
|
84
|
+
- **Use Default (`keepAlive: false`)** for screen-specific data (Product Details), so it clears to save memory when the screen is popped.
|
|
85
|
+
|
|
86
|
+
```dart
|
|
87
|
+
@Riverpod(keepAlive: true)
|
|
88
|
+
class UserSession extends _$UserSession { ... }
|
|
89
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Testing with Riverpod
|
|
2
|
+
|
|
3
|
+
Riverpod is designed for testability. You do not need complex dependency injection containers; you simply "override" providers in the test scope.
|
|
4
|
+
|
|
5
|
+
## Unit Testing (Notifiers)
|
|
6
|
+
|
|
7
|
+
Test notifiers in isolation using a `ProviderContainer`.
|
|
8
|
+
|
|
9
|
+
```dart
|
|
10
|
+
test('increment adds 1 to state', () {
|
|
11
|
+
// 1. Create container
|
|
12
|
+
final container = ProviderContainer();
|
|
13
|
+
addTearDown(container.dispose);
|
|
14
|
+
|
|
15
|
+
// 2. Listen to provider (required to initialize it)
|
|
16
|
+
container.listen(counterProvider, (_, __) {});
|
|
17
|
+
|
|
18
|
+
// 3. Act
|
|
19
|
+
container.read(counterProvider.notifier).increment();
|
|
20
|
+
|
|
21
|
+
// 4. Assert
|
|
22
|
+
expect(container.read(counterProvider), 1);
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Widget/Integration Testing (Overrides)
|
|
27
|
+
|
|
28
|
+
When testing widgets, wrap them in a `ProviderScope` and override the repository providers with mocks.
|
|
29
|
+
|
|
30
|
+
```dart
|
|
31
|
+
testWidgets('shows loading then data', (tester) async {
|
|
32
|
+
final mockRepo = MockUserRepository();
|
|
33
|
+
when(() => mockRepo.getAllUsers()).thenAnswer((_) async => [User(id: 1, name: 'Bob')]);
|
|
34
|
+
|
|
35
|
+
await tester.pumpWidget(
|
|
36
|
+
ProviderScope(
|
|
37
|
+
overrides: [
|
|
38
|
+
// 🔑 Replace the REAL repository with the MOCK
|
|
39
|
+
userRepositoryProvider.overrideWithValue(mockRepo),
|
|
40
|
+
],
|
|
41
|
+
child: const MaterialApp(home: UserListScreen()),
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// Assert Loading
|
|
46
|
+
expect(find.byType(CircularProgressIndicator), findsOneWidget);
|
|
47
|
+
|
|
48
|
+
// Assert Data
|
|
49
|
+
await tester.pumpAndSettle();
|
|
50
|
+
expect(find.text('Bob'), findsOneWidget);
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Mocking `AsyncNotifiers`
|
|
55
|
+
|
|
56
|
+
Sometimes you want to mock the _entire_ Controller/Notifier state, not just the repository.
|
|
57
|
+
|
|
58
|
+
```dart
|
|
59
|
+
// 1. Extend the generated class (or create a mock)
|
|
60
|
+
class MockUserController extends AutoDisposeAsyncNotifier<List<User>>
|
|
61
|
+
implements UserController {
|
|
62
|
+
@override
|
|
63
|
+
FutureOr<List<User>> build() => [];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 2. Override in ProviderScope
|
|
67
|
+
ProviderScope(
|
|
68
|
+
overrides: [
|
|
69
|
+
userControllerProvider.overrideWith(() => MockUserController()),
|
|
70
|
+
],
|
|
71
|
+
child: ...
|
|
72
|
+
)
|
|
73
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: flutter-riverpod
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
triggers: [riverpod, provider, state]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Riverpod
|
|
8
|
+
|
|
9
|
+
State management with Riverpod 2.x and code generation.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
dependencies:
|
|
15
|
+
flutter_riverpod: ^2.4.0
|
|
16
|
+
riverpod_annotation: ^2.3.0
|
|
17
|
+
|
|
18
|
+
dev_dependencies:
|
|
19
|
+
riverpod_generator: ^2.3.0
|
|
20
|
+
build_runner: ^2.4.0
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Provider Types
|
|
24
|
+
|
|
25
|
+
```dart
|
|
26
|
+
// Simple value
|
|
27
|
+
@riverpod
|
|
28
|
+
String greeting(GreetingRef ref) => 'Hello';
|
|
29
|
+
|
|
30
|
+
// Async data
|
|
31
|
+
@riverpod
|
|
32
|
+
Future<User> user(UserRef ref) async {
|
|
33
|
+
return ref.watch(apiProvider).getUser();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Notifier for mutable state
|
|
37
|
+
@riverpod
|
|
38
|
+
class Counter extends _$Counter {
|
|
39
|
+
@override
|
|
40
|
+
int build() => 0;
|
|
41
|
+
|
|
42
|
+
void increment() => state++;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Consumer Usage
|
|
47
|
+
|
|
48
|
+
```dart
|
|
49
|
+
class MyWidget extends ConsumerWidget {
|
|
50
|
+
@override
|
|
51
|
+
Widget build(BuildContext context, WidgetRef ref) {
|
|
52
|
+
final count = ref.watch(counterProvider);
|
|
53
|
+
return Text('$count');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Async Handling
|
|
59
|
+
|
|
60
|
+
```dart
|
|
61
|
+
ref.watch(userProvider).when(
|
|
62
|
+
data: (user) => UserCard(user),
|
|
63
|
+
loading: () => const CircularProgressIndicator(),
|
|
64
|
+
error: (e, st) => ErrorText(e.toString()),
|
|
65
|
+
);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Family Providers
|
|
69
|
+
|
|
70
|
+
```dart
|
|
71
|
+
@riverpod
|
|
72
|
+
Future<Post> post(PostRef ref, int id) async {
|
|
73
|
+
return ref.watch(apiProvider).getPost(id);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Usage
|
|
77
|
+
ref.watch(postProvider(42));
|
|
78
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Flutter Security
|
|
3
|
+
description: Security standards for Flutter applications based on OWASP Mobile.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [security, owasp, pii, encryption]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['lib/infrastructure/**', 'pubspec.yaml']
|
|
8
|
+
keywords: [secure_storage, obfuscate, jailbreak, pinning, PII, OWASP]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Mobile Security
|
|
12
|
+
|
|
13
|
+
## **Priority: P0 (CRITICAL)**
|
|
14
|
+
|
|
15
|
+
Standards for basic mobile security and PII protection.
|
|
16
|
+
|
|
17
|
+
## Implementation Guidelines
|
|
18
|
+
|
|
19
|
+
- **Secure Storage**: Use `flutter_secure_storage` for tokens/PII. Never use `shared_preferences`.
|
|
20
|
+
- **Hardcoding**: Never store API keys or secrets in Dart code. Use `--dart-define` or `.env`.
|
|
21
|
+
- **Obfuscation**: Always release with `--obfuscate` and `--split-debug-info`.
|
|
22
|
+
- **SSL Pinning**: For high-security apps, use `dio_certificate_pinning`.
|
|
23
|
+
- **Root Detection**: Use `flutter_jailbreak_detection` for financial/sensitive applications.
|
|
24
|
+
- **PII Masking**: Mask sensitive data (email, phone) in logs and analytics.
|
|
25
|
+
|
|
26
|
+
## Reference & Examples
|
|
27
|
+
|
|
28
|
+
For SSL Pinning and Secure Storage implementation details:
|
|
29
|
+
See [references/REFERENCE.md](references/REFERENCE.md).
|
|
30
|
+
|
|
31
|
+
## Related Topics
|
|
32
|
+
|
|
33
|
+
layer-based-clean-architecture | performance
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Mobile Security Reference
|
|
2
|
+
|
|
3
|
+
Detailed implementation patterns for OWASP Mobile compliance.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**Network Security**](network-security.md) - SSL Pinning and Security Headers.
|
|
8
|
+
- [**Secure Storage**](secure-storage-impl.md) - PII and Token management.
|
|
9
|
+
|
|
10
|
+
## **CI/CD Security Flag**
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Obfuscation during build
|
|
14
|
+
flutter build apk --obfuscate --split-debug-info=./debug-info
|
|
15
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Network Security & Certificate Pinning
|
|
2
|
+
|
|
3
|
+
## **SSL Pinning with Dio**
|
|
4
|
+
|
|
5
|
+
```dart
|
|
6
|
+
import 'package:dio/dio.dart';
|
|
7
|
+
import 'package:dio_certificate_pinning/dio_certificate_pinning.dart';
|
|
8
|
+
|
|
9
|
+
final dio = Dio();
|
|
10
|
+
dio.interceptors.add(CertificatePinningInterceptor(
|
|
11
|
+
allowedSHAFingerprints: [
|
|
12
|
+
"70:99:27:8B:54:4A:40:F5:30:DB:73:E3:64:36:0F:70:3D:09:A6:49",
|
|
13
|
+
],
|
|
14
|
+
));
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## **Security Headers Interceptor**
|
|
18
|
+
|
|
19
|
+
```dart
|
|
20
|
+
class SecurityInterceptor extends Interceptor {
|
|
21
|
+
@override
|
|
22
|
+
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
|
23
|
+
options.headers['X-Content-Type-Options'] = 'nosniff';
|
|
24
|
+
options.headers['X-Frame-Options'] = 'DENY';
|
|
25
|
+
super.onRequest(options, handler);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Flutter Testing Standards
|
|
3
|
+
description: Unit, widget, and integration testing using mocktail and bloc_test.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [testing, junit, mocktail, bloc_test, golden-tests]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/test/**.dart']
|
|
8
|
+
keywords: [test, group, expect, mocktail, blocTest, when, any]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Testing Standards
|
|
12
|
+
|
|
13
|
+
## **Priority: P1 (HIGH)**
|
|
14
|
+
|
|
15
|
+
Ensuring code reliability through multi-layered testing strategies.
|
|
16
|
+
|
|
17
|
+
## Structure
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
test/
|
|
21
|
+
├── unit/ # Business logic & mapping (Blocs, Repositories, UseCases)
|
|
22
|
+
├── widget/ # UI component behavior (Screens, Widgets)
|
|
23
|
+
└── integration/ # End-to-end flows
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Implementation Guidelines
|
|
27
|
+
|
|
28
|
+
- **Testing Pyramid**: Maintain ~70% Unit Tests, ~20% Widget Tests, ~10% Integration Tests.
|
|
29
|
+
- **Mocks**: Use `mocktail` for type-safe, boilerplate-free mocking.
|
|
30
|
+
- **Unit Tests**: Test logic in isolation. Verify all edge cases (Success, Failure, Exception).
|
|
31
|
+
- **Widget Tests**: Test high-value interactions (Button clicks, Error states, Loading indicators).
|
|
32
|
+
- **BLoC Tests**: Use `blocTest` to verify state emission sequences.
|
|
33
|
+
- **Code Coverage**: Aim for 80%+ coverage on Domain and Presentation (Logic) layers.
|
|
34
|
+
|
|
35
|
+
## Deep Dive References
|
|
36
|
+
|
|
37
|
+
- [Unit Testing Strategies](./references/unit-testing.md) (Test Data Builders, Mocktail)
|
|
38
|
+
- [Widget Testing Strategies](./references/widget-testing.md) (Robot Pattern)
|
|
39
|
+
- [Integration Testing](./references/integration-testing.md) (Shared Robots, Real Device)
|
|
40
|
+
- [Robot Pattern Implementation](./references/robot-pattern.md)
|
|
41
|
+
|
|
42
|
+
## Related Topics
|
|
43
|
+
|
|
44
|
+
layer-based-clean-architecture | dependency-injection | cicd
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Testing Standards Reference
|
|
2
|
+
|
|
3
|
+
Practical patterns for Unit, Widget, and Golden tests.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
- [**Unit Testing**](unit-testing.md) - Mocking, AAA pattern, Repository testing.
|
|
8
|
+
- [**Widget Testing**](widget-testing.md) - UI interactions, Finders, Pumping frames.
|
|
9
|
+
- [**BLoC Testing**](bloc-testing.md) - Using `blocTest` for state transitions.
|
|
10
|
+
|
|
11
|
+
## **Quick Assertions**
|
|
12
|
+
|
|
13
|
+
```dart
|
|
14
|
+
// Mocktail Stub
|
|
15
|
+
when(() => repository.fetchData()).thenAnswer((_) async => right(data));
|
|
16
|
+
|
|
17
|
+
// Expect Matchers
|
|
18
|
+
expect(state.isLoading, isTrue);
|
|
19
|
+
expect(find.text('Hello'), findsOneWidget);
|
|
20
|
+
verify(() => repository.fetchData()).called(1);
|
|
21
|
+
```
|