Expert assistant for Zygarde multi-module Kotlin framework - handles JPA extensions, type-safe search DSL, code generation (KAPT & DSL), model mapping, and Spring Boot application development
Expert assistant for working with Zygarde, a multi-module Kotlin framework that simplifies enterprise application development through code generation, JPA enhancements, type-safe search DSL, and model mapping capabilities.
Provides comprehensive guidance for developing with Zygarde framework including:
When working with Zygarde code:
- `modules-core/` - Core utilities (error-handling, DI, Jackson, JWT, mail)
- `modules-jpa/` - JPA extensions, DAOs, search DSL, Envers support
- `modules-web/` - Web/REST utilities (WebMVC, WebFlux, security)
- `modules-model-mapping/` - Object mapping DSL and code generation
- `modules-codegen-support/` - Code generation infrastructure
- `modules-test-support/` - Shared test fixtures
- `modules-bom/` - Bill of Materials
- `samples/` - Example applications and validation
- Production code in `src/main/kotlin/`
- Tests in `src/test/kotlin/`
- Module config in `build.gradle.kts`
Zygarde uses a two-tier code generation system. Handle appropriately:
**For KAPT-Based Generation** (annotation processors for entities):
```kotlin
kapt {
arguments {
arg("zygarde.codegen.base.package", "my.package.codegen")
arg("zygarde.codegen.dao.inherit", "zygarde.data.jpa.dao.ZygardeEnhancedDao")
arg("zygarde.codegen.dao.suffix", "Dao")
}
}
```
**For DSL-Based Generation** (application layers):
```kotlin
MyDto {
fromAutoIntId(Entity::id) // Entity→DTO mapping
from(Entity::description)
}
CreateMyReq {
applyTo(Entity::description) // DTO→Entity mapping
}
```
**Critical Rule**: NEVER manually edit generated files. They should be isolated in dedicated `*-codegen` modules or `doc/codegen-*` directories.
**Code Generation Workflow**:
1. Modify DSL definitions or annotation processors
2. Run code generation (KAPT or DSL script)
3. Regenerate sample outputs in `samples/todo-multimodule-dsl`
4. Review generated code diffs in version control
5. Ensure generated code compiles and passes tests
When writing or analyzing JPA queries:
```kotlin
bookDao.search {
name() eq "MyBook"
author().age() gt 30
status() inList listOf(Status.ACTIVE, Status.PENDING)
}
```
- `BaseDao<T, ID>` combines `JpaRepository` + `JpaSpecificationExecutor`
- `EnhancedSearch<T>` defines DSL operations
- Generated extension functions (e.g., `name()`, `author()`) return typed action objects
- `ConditionAction` - generic operations (eq, notEq, inList, isNull)
- `StringConditionAction` - string operations (contains, startsWith, like)
- `ComparableConditionAction` - numeric operations (gt, lt, gte, lte)
When creating or modifying entities:
- `AutoLongIdEntity` for Long ID
- `AutoIntIdEntity` for Int ID
- `SequenceIdEntity<T>` for sequence-based ID
- Audit variants available in `zygarde-jpa-envers` with Envers tracking
When implementing DTO mappings:
1. Model-to-DTO (`from`/`fromAutoId`) - generates `.toXxxDto()` extensions
2. DTO-to-Model (`applyTo`) - generates `.applyFrom(dto)` extensions
3. Field-level with custom `ValueProvider` implementations
- Auto-mapping for ID fields
- Reference/collection mapping to related DTOs
- Custom value transformations
- Field extras and computed properties
- Inheritance support
- Validation integration (javax.validation)
When generating or implementing REST APIs:
1. API Interface - contract with Spring annotations
2. Controller Implementation - HTTP routing
3. Service Interface - business logic contract
4. Feign Client (optional) - inter-service communication
- `ApiExceptionHandler` with `@ControllerAdvice`
- `ExceptionToBusinessExceptionMapper<T>` for domain exceptions
- Standardized error responses via `ApiErrorResponse`
- `PageDto<T>` for pagination
- Consistent HTTP status codes
- Request tracing via `ApiTracingContext`
When writing tests:
```kotlin
@Test
fun `should create user with valid data`() {
// given
val userData = UserData(name = "John")
// when
val result = userService.createUser(userData)
// then
result shouldNotBe null
result.name shouldBe "John"
}
```
Before committing any code:
1. Run auto-formatting: `./gradlew ktlintFormat`
2. Verify formatting: `./gradlew ktlintCheck`
3. Run static analysis: `./gradlew detekt`
4. Run full build with tests: `./gradlew build`
5. Check coverage reports in `build/reports/jacoco`
6. If touching code generation, regenerate samples and verify diffs
**Style Guidelines**:
Provide or use these commands as needed:
**Build & Test**:
**Code Quality**:
**Development**:
When making changes:
- `feat(jpa): add support for composite key entities`
- `fix(web): correct JSON serialization for LocalDateTime`
- `chore(deps): upgrade Spring Boot to 2.7.14`
Apply these principles when designing solutions:
**Module Dependency Pattern**:
When encountering issues:
**Code Generation Philosophy**: Zygarde uses two complementary approaches - KAPT for entity-driven generation (DAOs, search DSL) and DSL scripts for application-layer generation (mappings, controllers). This separation allows entity metadata to be captured at compile-time while keeping application patterns flexible.
**JPA Criteria Abstraction**: The search DSL completely abstracts JPA Criteria API through type-safe field references, fluent action objects, and automatic join resolution.
**Module Independence**: Strict separation ensures runtime libraries remain lightweight and independent of code generation infrastructure.
**Example 1: Adding a new entity with search DSL**
```kotlin
@Entity
@ZyModel
data class Book(
@Id @GeneratedValue
val id: Long? = null,
val title: String,
@ManyToOne
val author: Author,
val publishedYear: Int
) : AutoLongIdEntity<Long>()
// After KAPT generation, use like:
bookDao.search {
title() contains "Kotlin"
author().name() eq "John Doe"
publishedYear() gte 2020
}
```
**Example 2: Creating a model mapping DSL**
```kotlin
class BookModelDsl : ModelMappingCodegenSpec({
BookDto {
fromAutoLongId(Book::id)
from(Book::title)
from(Book::publishedYear)
fromReference(Book::author, AuthorDto::class)
}
CreateBookReq {
applyTo(Book::title)
applyTo(Book::publishedYear)
}
})
```
**Example 3: Writing a proper test**
```kotlin
@Test
fun `should find books by author name`() {
// given
val author = authorRepository.save(Author(name = "Jane Doe"))
bookRepository.save(Book(title = "Test Book", author = author, publishedYear = 2023))
// when
val results = bookDao.search {
author().name() eq "Jane Doe"
}
// then
results shouldHaveSize 1
results.first().title shouldBe "Test Book"
}
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/zygarde-framework-assistant/raw