@ngxtm/devkit 3.4.0 → 3.4.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/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
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Sea ORM Entity Patterns
|
|
2
|
+
|
|
3
|
+
## Entity Definition
|
|
4
|
+
|
|
5
|
+
```rust
|
|
6
|
+
use sea_orm::entity::prelude::*;
|
|
7
|
+
|
|
8
|
+
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
|
9
|
+
#[sea_orm(table_name = "users")]
|
|
10
|
+
pub struct Model {
|
|
11
|
+
#[sea_orm(primary_key)]
|
|
12
|
+
pub id: i32,
|
|
13
|
+
pub name: String,
|
|
14
|
+
#[sea_orm(unique)]
|
|
15
|
+
pub email: String,
|
|
16
|
+
pub age: Option<i32>,
|
|
17
|
+
pub active: bool,
|
|
18
|
+
pub created_at: DateTimeUtc,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
|
22
|
+
pub enum Relation {
|
|
23
|
+
#[sea_orm(has_many = "super::post::Entity")]
|
|
24
|
+
Posts,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
impl Related<super::post::Entity> for Entity {
|
|
28
|
+
fn to() -> RelationDef {
|
|
29
|
+
Relation::Posts.def()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
impl ActiveModelBehavior for ActiveModel {}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Basic CRUD
|
|
37
|
+
|
|
38
|
+
```rust
|
|
39
|
+
use sea_orm::{Database, EntityTrait, ActiveModelTrait, Set};
|
|
40
|
+
|
|
41
|
+
async fn crud_examples(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|
42
|
+
// Create
|
|
43
|
+
let user = user::ActiveModel {
|
|
44
|
+
name: Set("John".to_owned()),
|
|
45
|
+
email: Set("john@example.com".to_owned()),
|
|
46
|
+
active: Set(true),
|
|
47
|
+
..Default::default()
|
|
48
|
+
};
|
|
49
|
+
let user = user.insert(db).await?;
|
|
50
|
+
|
|
51
|
+
// Read one
|
|
52
|
+
let user = User::find_by_id(1).one(db).await?;
|
|
53
|
+
|
|
54
|
+
// Read with conditions
|
|
55
|
+
let users = User::find()
|
|
56
|
+
.filter(user::Column::Active.eq(true))
|
|
57
|
+
.filter(user::Column::Age.gt(18))
|
|
58
|
+
.order_by_asc(user::Column::Name)
|
|
59
|
+
.limit(10)
|
|
60
|
+
.all(db)
|
|
61
|
+
.await?;
|
|
62
|
+
|
|
63
|
+
// Update
|
|
64
|
+
let mut user: user::ActiveModel = user.unwrap().into();
|
|
65
|
+
user.name = Set("Jane".to_owned());
|
|
66
|
+
let user = user.update(db).await?;
|
|
67
|
+
|
|
68
|
+
// Delete
|
|
69
|
+
User::delete_by_id(1).exec(db).await?;
|
|
70
|
+
|
|
71
|
+
Ok(())
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Relations
|
|
76
|
+
|
|
77
|
+
```rust
|
|
78
|
+
// Post entity
|
|
79
|
+
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
|
80
|
+
#[sea_orm(table_name = "posts")]
|
|
81
|
+
pub struct Model {
|
|
82
|
+
#[sea_orm(primary_key)]
|
|
83
|
+
pub id: i32,
|
|
84
|
+
pub title: String,
|
|
85
|
+
pub user_id: i32,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
|
89
|
+
pub enum Relation {
|
|
90
|
+
#[sea_orm(
|
|
91
|
+
belongs_to = "super::user::Entity",
|
|
92
|
+
from = "Column::UserId",
|
|
93
|
+
to = "super::user::Column::Id"
|
|
94
|
+
)]
|
|
95
|
+
User,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
impl Related<super::user::Entity> for Entity {
|
|
99
|
+
fn to() -> RelationDef {
|
|
100
|
+
Relation::User.def()
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Query with relations
|
|
105
|
+
async fn with_relations(db: &DatabaseConnection) -> Result<(), DbErr> {
|
|
106
|
+
// Eager loading
|
|
107
|
+
let users_with_posts = User::find()
|
|
108
|
+
.find_with_related(Post)
|
|
109
|
+
.all(db)
|
|
110
|
+
.await?;
|
|
111
|
+
|
|
112
|
+
for (user, posts) in users_with_posts {
|
|
113
|
+
println!("User: {}", user.name);
|
|
114
|
+
for post in posts {
|
|
115
|
+
println!(" Post: {}", post.title);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Join
|
|
120
|
+
let results = User::find()
|
|
121
|
+
.inner_join(Post)
|
|
122
|
+
.filter(post::Column::Title.contains("rust"))
|
|
123
|
+
.all(db)
|
|
124
|
+
.await?;
|
|
125
|
+
|
|
126
|
+
Ok(())
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Transactions
|
|
131
|
+
|
|
132
|
+
```rust
|
|
133
|
+
use sea_orm::TransactionTrait;
|
|
134
|
+
|
|
135
|
+
async fn transfer(db: &DatabaseConnection, from: i32, to: i32, amount: i64) -> Result<(), DbErr> {
|
|
136
|
+
db.transaction::<_, (), DbErr>(|txn| {
|
|
137
|
+
Box::pin(async move {
|
|
138
|
+
// Debit
|
|
139
|
+
let from_account = Account::find_by_id(from).one(txn).await?.unwrap();
|
|
140
|
+
let mut from_account: account::ActiveModel = from_account.into();
|
|
141
|
+
from_account.balance = Set(from_account.balance.unwrap() - amount);
|
|
142
|
+
from_account.update(txn).await?;
|
|
143
|
+
|
|
144
|
+
// Credit
|
|
145
|
+
let to_account = Account::find_by_id(to).one(txn).await?.unwrap();
|
|
146
|
+
let mut to_account: account::ActiveModel = to_account.into();
|
|
147
|
+
to_account.balance = Set(to_account.balance.unwrap() + amount);
|
|
148
|
+
to_account.update(txn).await?;
|
|
149
|
+
|
|
150
|
+
Ok(())
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
.await
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Custom Queries
|
|
158
|
+
|
|
159
|
+
```rust
|
|
160
|
+
use sea_orm::{FromQueryResult, Statement};
|
|
161
|
+
|
|
162
|
+
#[derive(Debug, FromQueryResult)]
|
|
163
|
+
struct UserStats {
|
|
164
|
+
name: String,
|
|
165
|
+
post_count: i64,
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async fn custom_query(db: &DatabaseConnection) -> Result<Vec<UserStats>, DbErr> {
|
|
169
|
+
UserStats::find_by_statement(Statement::from_sql_and_values(
|
|
170
|
+
db.get_database_backend(),
|
|
171
|
+
r#"
|
|
172
|
+
SELECT u.name, COUNT(p.id) as post_count
|
|
173
|
+
FROM users u
|
|
174
|
+
LEFT JOIN posts p ON u.id = p.user_id
|
|
175
|
+
GROUP BY u.id, u.name
|
|
176
|
+
"#,
|
|
177
|
+
vec![],
|
|
178
|
+
))
|
|
179
|
+
.all(db)
|
|
180
|
+
.await
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Migrations
|
|
185
|
+
|
|
186
|
+
```rust
|
|
187
|
+
// migration/src/m20220101_000001_create_users.rs
|
|
188
|
+
use sea_orm_migration::prelude::*;
|
|
189
|
+
|
|
190
|
+
#[derive(DeriveMigrationName)]
|
|
191
|
+
pub struct Migration;
|
|
192
|
+
|
|
193
|
+
#[async_trait::async_trait]
|
|
194
|
+
impl MigrationTrait for Migration {
|
|
195
|
+
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
|
196
|
+
manager
|
|
197
|
+
.create_table(
|
|
198
|
+
Table::create()
|
|
199
|
+
.table(Users::Table)
|
|
200
|
+
.if_not_exists()
|
|
201
|
+
.col(ColumnDef::new(Users::Id).integer().not_null().auto_increment().primary_key())
|
|
202
|
+
.col(ColumnDef::new(Users::Name).string().not_null())
|
|
203
|
+
.col(ColumnDef::new(Users::Email).string().unique_key().not_null())
|
|
204
|
+
.to_owned(),
|
|
205
|
+
)
|
|
206
|
+
.await
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
|
210
|
+
manager.drop_table(Table::drop().table(Users::Table).to_owned()).await
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#[derive(Iden)]
|
|
215
|
+
enum Users {
|
|
216
|
+
Table,
|
|
217
|
+
Id,
|
|
218
|
+
Name,
|
|
219
|
+
Email,
|
|
220
|
+
}
|
|
221
|
+
```
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Serde Serialization
|
|
3
|
+
description: Rust serialization/deserialization framework for JSON, YAML, TOML, and more.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [rust, serde, serialization, json]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.rs']
|
|
8
|
+
keywords: [Serialize, Deserialize, serde, serde_json]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Serde Standards
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
```rust
|
|
16
|
+
use serde::{Serialize, Deserialize};
|
|
17
|
+
|
|
18
|
+
#[derive(Serialize, Deserialize, Debug)]
|
|
19
|
+
struct User {
|
|
20
|
+
id: u64,
|
|
21
|
+
name: String,
|
|
22
|
+
email: String,
|
|
23
|
+
#[serde(default)]
|
|
24
|
+
active: bool,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Serialize to JSON
|
|
28
|
+
let user = User { id: 1, name: "Alice".into(), email: "a@b.com".into(), active: true };
|
|
29
|
+
let json = serde_json::to_string(&user)?;
|
|
30
|
+
|
|
31
|
+
// Deserialize from JSON
|
|
32
|
+
let user: User = serde_json::from_str(&json)?;
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Field Attributes
|
|
36
|
+
|
|
37
|
+
```rust
|
|
38
|
+
#[derive(Serialize, Deserialize)]
|
|
39
|
+
struct Config {
|
|
40
|
+
// Rename field in JSON
|
|
41
|
+
#[serde(rename = "apiKey")]
|
|
42
|
+
api_key: String,
|
|
43
|
+
|
|
44
|
+
// Skip serializing if None
|
|
45
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
46
|
+
description: Option<String>,
|
|
47
|
+
|
|
48
|
+
// Default value if missing
|
|
49
|
+
#[serde(default = "default_timeout")]
|
|
50
|
+
timeout_secs: u64,
|
|
51
|
+
|
|
52
|
+
// Skip entirely
|
|
53
|
+
#[serde(skip)]
|
|
54
|
+
internal_state: bool,
|
|
55
|
+
|
|
56
|
+
// Flatten nested struct
|
|
57
|
+
#[serde(flatten)]
|
|
58
|
+
metadata: Metadata,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fn default_timeout() -> u64 { 30 }
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Enums
|
|
65
|
+
|
|
66
|
+
```rust
|
|
67
|
+
#[derive(Serialize, Deserialize)]
|
|
68
|
+
#[serde(tag = "type")] // Tagged union
|
|
69
|
+
enum Event {
|
|
70
|
+
#[serde(rename = "user_created")]
|
|
71
|
+
UserCreated { id: u64, email: String },
|
|
72
|
+
|
|
73
|
+
#[serde(rename = "user_deleted")]
|
|
74
|
+
UserDeleted { id: u64 },
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Serializes as: {"type": "user_created", "id": 1, "email": "..."}
|
|
78
|
+
|
|
79
|
+
// Untagged variant
|
|
80
|
+
#[derive(Serialize, Deserialize)]
|
|
81
|
+
#[serde(untagged)]
|
|
82
|
+
enum Value {
|
|
83
|
+
Integer(i64),
|
|
84
|
+
Float(f64),
|
|
85
|
+
String(String),
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Custom Serialization
|
|
90
|
+
|
|
91
|
+
```rust
|
|
92
|
+
use serde::{Serializer, Deserializer};
|
|
93
|
+
|
|
94
|
+
#[derive(Serialize, Deserialize)]
|
|
95
|
+
struct Record {
|
|
96
|
+
#[serde(serialize_with = "serialize_datetime")]
|
|
97
|
+
#[serde(deserialize_with = "deserialize_datetime")]
|
|
98
|
+
created_at: DateTime<Utc>,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
fn serialize_datetime<S>(dt: &DateTime<Utc>, s: S) -> Result<S::Ok, S::Error>
|
|
102
|
+
where S: Serializer {
|
|
103
|
+
s.serialize_str(&dt.to_rfc3339())
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fn deserialize_datetime<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
|
|
107
|
+
where D: Deserializer<'de> {
|
|
108
|
+
let s = String::deserialize(d)?;
|
|
109
|
+
DateTime::parse_from_rfc3339(&s)
|
|
110
|
+
.map(|dt| dt.with_timezone(&Utc))
|
|
111
|
+
.map_err(serde::de::Error::custom)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Format Support
|
|
116
|
+
|
|
117
|
+
| Format | Crate | Use Case |
|
|
118
|
+
|--------|-------|----------|
|
|
119
|
+
| JSON | `serde_json` | APIs, config |
|
|
120
|
+
| YAML | `serde_yaml` | Config files |
|
|
121
|
+
| TOML | `toml` | Cargo.toml style |
|
|
122
|
+
| MessagePack | `rmp-serde` | Binary, compact |
|
|
123
|
+
| CBOR | `ciborium` | Binary, standards |
|
|
124
|
+
|
|
125
|
+
## Validation with Derive
|
|
126
|
+
|
|
127
|
+
```rust
|
|
128
|
+
use serde::Deserialize;
|
|
129
|
+
use validator::Validate;
|
|
130
|
+
|
|
131
|
+
#[derive(Deserialize, Validate)]
|
|
132
|
+
struct CreateUser {
|
|
133
|
+
#[validate(length(min = 1, max = 100))]
|
|
134
|
+
name: String,
|
|
135
|
+
|
|
136
|
+
#[validate(email)]
|
|
137
|
+
email: String,
|
|
138
|
+
|
|
139
|
+
#[validate(range(min = 18, max = 120))]
|
|
140
|
+
age: u8,
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Best Practices
|
|
145
|
+
|
|
146
|
+
1. **Deny unknown fields**: `#[serde(deny_unknown_fields)]` for strict parsing
|
|
147
|
+
2. **Rename all**: `#[serde(rename_all = "camelCase")]` for consistent naming
|
|
148
|
+
3. **Default trait**: Implement `Default` for optional defaults
|
|
149
|
+
4. **Error context**: Use `anyhow` or custom errors for better messages
|
|
150
|
+
5. **Performance**: Use `serde_json::from_slice` for bytes, avoid string conversion
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Rust Serde References
|
|
2
|
+
|
|
3
|
+
## References
|
|
4
|
+
|
|
5
|
+
- [**Serialization Patterns**](serialization-patterns.md) - Derive, attributes, custom
|
|
6
|
+
|
|
7
|
+
## Quick Checks
|
|
8
|
+
|
|
9
|
+
- [ ] Use derive macros for simple cases
|
|
10
|
+
- [ ] Field attributes for customization
|
|
11
|
+
- [ ] rename_all for case conventions
|
|
12
|
+
- [ ] skip_serializing_if for optional fields
|
|
13
|
+
- [ ] Custom serializers for complex types
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Serde Serialization Patterns
|
|
2
|
+
|
|
3
|
+
## Basic Derive
|
|
4
|
+
|
|
5
|
+
```rust
|
|
6
|
+
use serde::{Deserialize, Serialize};
|
|
7
|
+
|
|
8
|
+
#[derive(Serialize, Deserialize, Debug)]
|
|
9
|
+
struct User {
|
|
10
|
+
id: u64,
|
|
11
|
+
name: String,
|
|
12
|
+
email: String,
|
|
13
|
+
#[serde(default)]
|
|
14
|
+
active: bool,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Usage
|
|
18
|
+
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
19
|
+
let user = User {
|
|
20
|
+
id: 1,
|
|
21
|
+
name: "John".into(),
|
|
22
|
+
email: "john@example.com".into(),
|
|
23
|
+
active: true,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// To JSON
|
|
27
|
+
let json = serde_json::to_string(&user)?;
|
|
28
|
+
let json_pretty = serde_json::to_string_pretty(&user)?;
|
|
29
|
+
|
|
30
|
+
// From JSON
|
|
31
|
+
let parsed: User = serde_json::from_str(&json)?;
|
|
32
|
+
|
|
33
|
+
Ok(())
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Field Attributes
|
|
38
|
+
|
|
39
|
+
```rust
|
|
40
|
+
#[derive(Serialize, Deserialize)]
|
|
41
|
+
#[serde(rename_all = "camelCase")]
|
|
42
|
+
struct User {
|
|
43
|
+
user_id: u64, // Serializes as "userId"
|
|
44
|
+
|
|
45
|
+
#[serde(rename = "userName")]
|
|
46
|
+
name: String,
|
|
47
|
+
|
|
48
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
49
|
+
bio: Option<String>,
|
|
50
|
+
|
|
51
|
+
#[serde(skip)]
|
|
52
|
+
internal_state: String,
|
|
53
|
+
|
|
54
|
+
#[serde(default = "default_role")]
|
|
55
|
+
role: String,
|
|
56
|
+
|
|
57
|
+
#[serde(flatten)]
|
|
58
|
+
metadata: Metadata,
|
|
59
|
+
|
|
60
|
+
#[serde(with = "chrono::serde::ts_seconds")]
|
|
61
|
+
created_at: DateTime<Utc>,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fn default_role() -> String {
|
|
65
|
+
"user".into()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#[derive(Serialize, Deserialize)]
|
|
69
|
+
struct Metadata {
|
|
70
|
+
source: String,
|
|
71
|
+
version: u32,
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Enum Representations
|
|
76
|
+
|
|
77
|
+
```rust
|
|
78
|
+
// Default: externally tagged
|
|
79
|
+
#[derive(Serialize, Deserialize)]
|
|
80
|
+
enum Message {
|
|
81
|
+
Text(String), // {"Text": "hello"}
|
|
82
|
+
Image { url: String }, // {"Image": {"url": "..."}}
|
|
83
|
+
Ping, // "Ping"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Internally tagged
|
|
87
|
+
#[derive(Serialize, Deserialize)]
|
|
88
|
+
#[serde(tag = "type")]
|
|
89
|
+
enum Event {
|
|
90
|
+
Click { x: i32, y: i32 }, // {"type": "Click", "x": 10, "y": 20}
|
|
91
|
+
KeyPress { key: String },
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Adjacently tagged
|
|
95
|
+
#[derive(Serialize, Deserialize)]
|
|
96
|
+
#[serde(tag = "type", content = "data")]
|
|
97
|
+
enum Response {
|
|
98
|
+
Success(Data), // {"type": "Success", "data": {...}}
|
|
99
|
+
Error(String),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Untagged
|
|
103
|
+
#[derive(Serialize, Deserialize)]
|
|
104
|
+
#[serde(untagged)]
|
|
105
|
+
enum Value {
|
|
106
|
+
Integer(i64),
|
|
107
|
+
Float(f64),
|
|
108
|
+
Text(String),
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Custom Serializers
|
|
113
|
+
|
|
114
|
+
```rust
|
|
115
|
+
use serde::{Serializer, Deserializer};
|
|
116
|
+
|
|
117
|
+
#[derive(Serialize, Deserialize)]
|
|
118
|
+
struct Config {
|
|
119
|
+
#[serde(serialize_with = "serialize_duration")]
|
|
120
|
+
#[serde(deserialize_with = "deserialize_duration")]
|
|
121
|
+
timeout: Duration,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
fn serialize_duration<S>(duration: &Duration, s: S) -> Result<S::Ok, S::Error>
|
|
125
|
+
where
|
|
126
|
+
S: Serializer,
|
|
127
|
+
{
|
|
128
|
+
s.serialize_u64(duration.as_secs())
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fn deserialize_duration<'de, D>(d: D) -> Result<Duration, D::Error>
|
|
132
|
+
where
|
|
133
|
+
D: Deserializer<'de>,
|
|
134
|
+
{
|
|
135
|
+
let secs = u64::deserialize(d)?;
|
|
136
|
+
Ok(Duration::from_secs(secs))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Or use a module
|
|
140
|
+
mod duration_secs {
|
|
141
|
+
use super::*;
|
|
142
|
+
|
|
143
|
+
pub fn serialize<S>(duration: &Duration, s: S) -> Result<S::Ok, S::Error>
|
|
144
|
+
where S: Serializer {
|
|
145
|
+
s.serialize_u64(duration.as_secs())
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pub fn deserialize<'de, D>(d: D) -> Result<Duration, D::Error>
|
|
149
|
+
where D: Deserializer<'de> {
|
|
150
|
+
let secs = u64::deserialize(d)?;
|
|
151
|
+
Ok(Duration::from_secs(secs))
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#[derive(Serialize, Deserialize)]
|
|
156
|
+
struct Config {
|
|
157
|
+
#[serde(with = "duration_secs")]
|
|
158
|
+
timeout: Duration,
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Generic Types
|
|
163
|
+
|
|
164
|
+
```rust
|
|
165
|
+
#[derive(Serialize, Deserialize)]
|
|
166
|
+
struct Response<T> {
|
|
167
|
+
success: bool,
|
|
168
|
+
data: Option<T>,
|
|
169
|
+
error: Option<String>,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#[derive(Serialize, Deserialize)]
|
|
173
|
+
#[serde(bound = "T: Serialize + DeserializeOwned")]
|
|
174
|
+
struct Paginated<T> {
|
|
175
|
+
items: Vec<T>,
|
|
176
|
+
page: u32,
|
|
177
|
+
total: u32,
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Different Formats
|
|
182
|
+
|
|
183
|
+
```rust
|
|
184
|
+
// JSON
|
|
185
|
+
let json = serde_json::to_string(&data)?;
|
|
186
|
+
let data: Data = serde_json::from_str(&json)?;
|
|
187
|
+
|
|
188
|
+
// YAML
|
|
189
|
+
let yaml = serde_yaml::to_string(&data)?;
|
|
190
|
+
let data: Data = serde_yaml::from_str(&yaml)?;
|
|
191
|
+
|
|
192
|
+
// TOML
|
|
193
|
+
let toml = toml::to_string(&data)?;
|
|
194
|
+
let data: Data = toml::from_str(&toml)?;
|
|
195
|
+
|
|
196
|
+
// Bincode (binary)
|
|
197
|
+
let bytes = bincode::serialize(&data)?;
|
|
198
|
+
let data: Data = bincode::deserialize(&bytes)?;
|
|
199
|
+
```
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: SQLx Database
|
|
3
|
+
description: Async Rust SQL toolkit with compile-time checked queries.
|
|
4
|
+
metadata:
|
|
5
|
+
labels: [rust, sqlx, database, async, postgresql]
|
|
6
|
+
triggers:
|
|
7
|
+
files: ['**/*.rs', 'sqlx-data.json']
|
|
8
|
+
keywords: [sqlx, query, query_as, PgPool]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# SQLx Standards
|
|
12
|
+
|
|
13
|
+
## Connection Pool
|
|
14
|
+
|
|
15
|
+
```rust
|
|
16
|
+
use sqlx::postgres::PgPoolOptions;
|
|
17
|
+
|
|
18
|
+
let pool = PgPoolOptions::new()
|
|
19
|
+
.max_connections(5)
|
|
20
|
+
.connect("postgres://user:pass@localhost/db")
|
|
21
|
+
.await?;
|
|
22
|
+
|
|
23
|
+
// Or from environment
|
|
24
|
+
let pool = PgPool::connect(&std::env::var("DATABASE_URL")?).await?;
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Compile-Time Checked Queries
|
|
28
|
+
|
|
29
|
+
```rust
|
|
30
|
+
// Requires DATABASE_URL at compile time
|
|
31
|
+
let user = sqlx::query_as!(
|
|
32
|
+
User,
|
|
33
|
+
"SELECT id, name, email FROM users WHERE id = $1",
|
|
34
|
+
user_id
|
|
35
|
+
)
|
|
36
|
+
.fetch_one(&pool)
|
|
37
|
+
.await?;
|
|
38
|
+
|
|
39
|
+
// Query with type override
|
|
40
|
+
let count = sqlx::query_scalar!(
|
|
41
|
+
r#"SELECT COUNT(*) as "count!" FROM users"#
|
|
42
|
+
)
|
|
43
|
+
.fetch_one(&pool)
|
|
44
|
+
.await?;
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Runtime Queries
|
|
48
|
+
|
|
49
|
+
```rust
|
|
50
|
+
use sqlx::{query, query_as, FromRow};
|
|
51
|
+
|
|
52
|
+
#[derive(FromRow)]
|
|
53
|
+
struct User {
|
|
54
|
+
id: i64,
|
|
55
|
+
name: String,
|
|
56
|
+
email: String,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Named struct mapping
|
|
60
|
+
let users: Vec<User> = query_as("SELECT * FROM users WHERE active = $1")
|
|
61
|
+
.bind(true)
|
|
62
|
+
.fetch_all(&pool)
|
|
63
|
+
.await?;
|
|
64
|
+
|
|
65
|
+
// Dynamic query
|
|
66
|
+
let user = query("SELECT * FROM users WHERE id = $1")
|
|
67
|
+
.bind(user_id)
|
|
68
|
+
.fetch_optional(&pool)
|
|
69
|
+
.await?;
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Fetch Methods
|
|
73
|
+
|
|
74
|
+
| Method | Returns | Use Case |
|
|
75
|
+
|--------|---------|----------|
|
|
76
|
+
| `fetch_one` | `T` | Exactly one row expected |
|
|
77
|
+
| `fetch_optional` | `Option<T>` | Zero or one row |
|
|
78
|
+
| `fetch_all` | `Vec<T>` | All rows in memory |
|
|
79
|
+
| `fetch` | `Stream<T>` | Large result sets |
|
|
80
|
+
|
|
81
|
+
## Transactions
|
|
82
|
+
|
|
83
|
+
```rust
|
|
84
|
+
let mut tx = pool.begin().await?;
|
|
85
|
+
|
|
86
|
+
sqlx::query("INSERT INTO users (name) VALUES ($1)")
|
|
87
|
+
.bind(&user.name)
|
|
88
|
+
.execute(&mut *tx)
|
|
89
|
+
.await?;
|
|
90
|
+
|
|
91
|
+
sqlx::query("INSERT INTO audit_log (action) VALUES ($1)")
|
|
92
|
+
.bind("user_created")
|
|
93
|
+
.execute(&mut *tx)
|
|
94
|
+
.await?;
|
|
95
|
+
|
|
96
|
+
tx.commit().await?;
|
|
97
|
+
|
|
98
|
+
// Or automatic rollback on drop
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Migrations
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Create migration
|
|
105
|
+
sqlx migrate add create_users_table
|
|
106
|
+
|
|
107
|
+
# Run migrations
|
|
108
|
+
sqlx migrate run
|
|
109
|
+
|
|
110
|
+
# Revert last migration
|
|
111
|
+
sqlx migrate revert
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```rust
|
|
115
|
+
// Run embedded migrations at startup
|
|
116
|
+
sqlx::migrate!("./migrations")
|
|
117
|
+
.run(&pool)
|
|
118
|
+
.await?;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Type Mappings
|
|
122
|
+
|
|
123
|
+
| PostgreSQL | Rust | Notes |
|
|
124
|
+
|------------|------|-------|
|
|
125
|
+
| `BIGINT` | `i64` | |
|
|
126
|
+
| `INTEGER` | `i32` | |
|
|
127
|
+
| `TEXT/VARCHAR` | `String` | |
|
|
128
|
+
| `BOOLEAN` | `bool` | |
|
|
129
|
+
| `TIMESTAMP` | `chrono::NaiveDateTime` | Requires `chrono` feature |
|
|
130
|
+
| `TIMESTAMPTZ` | `chrono::DateTime<Utc>` | |
|
|
131
|
+
| `UUID` | `uuid::Uuid` | Requires `uuid` feature |
|
|
132
|
+
| `JSONB` | `serde_json::Value` | Requires `json` feature |
|
|
133
|
+
|
|
134
|
+
## Best Practices
|
|
135
|
+
|
|
136
|
+
1. **Compile-time checks**: Use `query!` macros when possible
|
|
137
|
+
2. **Connection limits**: Match pool size to Postgres `max_connections`
|
|
138
|
+
3. **Prepared statements**: sqlx caches automatically per connection
|
|
139
|
+
4. **Offline mode**: Generate `sqlx-data.json` for CI without database
|
|
140
|
+
5. **Nullable columns**: Use `Option<T>` for nullable, or override with `"column!"`
|