@patrickjs/kotlin-ktor-development-cursorrules-prom
## Instruction to developer: save this file as .cursorrules and place it on the root project directory ## Core Principles
prpm install @patrickjs/kotlin-ktor-development-cursorrules-prom0 total downloads
š Full Prompt Content
## Instruction to developer: save this file as .cursorrules and place it on the root project directory
## Core Principles
- Follow **SOLID**, **DRY**, **KISS**, and **YAGNI** principles
- Adhere to **OWASP** security best practices
- Break tasks into smallest units and solve problems step-by-step
## Technology Stack
- **Framework**: Kotlin Ktor with Kotlin 2.1.20+
- **JDK**: 21 (LTS)
- **Build**: Gradle with Kotlin DSL
- **Dependencies**: Ktor Server Core/Netty, kotlinx.serialization, Exposed, HikariCP, kotlin-logging, Koin, Kotest
## Application Structure (Feature-Based)
- **Organize by business features, not technical layers**
- Each feature is self-contained with all related components
- Promotes modularity, reusability, and better team collaboration
- Makes codebase easier to navigate and maintain
- Enables parallel development on different features
```
src/main/kotlin/com/company/app/
āāā common/ # Shared utilities, extensions
āāā config/ # Application configuration, DI
āāā features/
āāā auth/ # Feature directory
ā āāā models/
ā āāā repositories/
ā āāā services/
ā āāā routes/
āāā users/ # Another feature
āāā ...
```
Test structure mirrors the feature-based organization:
```
src/test/kotlin/com/company/app/
āāā common/
āāā features/
āāā auth/
ā āāā models/
ā āāā repositories/
ā āāā services/
ā āāā routes/
āāā users/
āāā ...
```
## Application Logic Design
1. Route handlers: Handle requests/responses only
2. Services: Contain business logic, call repositories
3. Repositories: Handle database operations
4. Entity classes: Data classes for database models
5. DTOs: Data transfer between layers
## Entities & Data Classes
- Use Kotlin data classes with proper validation
- Define Table objects when using Exposed ORM
- Use UUID or auto-incrementing integers for IDs
## Repository Pattern
```kotlin
interface UserRepository {
suspend fun findById(id: UUID): UserDTO?
suspend fun create(user: CreateUserRequest): UserDTO
suspend fun update(id: UUID, user: UpdateUserRequest): UserDTO?
suspend fun delete(id: UUID): Boolean
}
class UserRepositoryImpl : UserRepository {
override suspend fun findById(id: UUID): UserDTO? = withContext(Dispatchers.IO) {
transaction {
Users.select { Users.id eq id }
.mapNotNull { it.toUserDTO() }
.singleOrNull()
}
}
// Other implementations...
}
```
## Service Layer
```kotlin
interface UserService {
suspend fun getUserById(id: UUID): UserDTO
suspend fun createUser(request: CreateUserRequest): UserDTO
suspend fun updateUser(id: UUID, request: UpdateUserRequest): UserDTO
suspend fun deleteUser(id: UUID)
}
class UserServiceImpl(
private val userRepository: UserRepository
) : UserService {
override suspend fun getUserById(id: UUID): UserDTO {
return userRepository.findById(id) ?: throw ResourceNotFoundException("User", id.toString())
}
// Other implementations...
}
```
## Route Handlers
```kotlin
fun Application.configureUserRoutes(userService: UserService) {
routing {
route("/api/users") {
get("/{id}") {
val id = call.parameters["id"]?.let { UUID.fromString(it) }
?: throw ValidationException("Invalid ID format")
val user = userService.getUserById(id)
call.respond(ApiResponse("SUCCESS", "User retrieved", user))
}
// Other routes...
}
}
}
```
## Error Handling
```kotlin
open class ApplicationException(
message: String,
val statusCode: HttpStatusCode = HttpStatusCode.InternalServerError
) : RuntimeException(message)
class ResourceNotFoundException(resource: String, id: String) :
ApplicationException("$resource with ID $id not found", HttpStatusCode.NotFound)
fun Application.configureExceptions() {
install(StatusPages) {
exception<ResourceNotFoundException> { call, cause ->
call.respond(cause.statusCode, ApiResponse("ERROR", cause.message ?: "Resource not found"))
}
exception<Throwable> { call, cause ->
call.respond(HttpStatusCode.InternalServerError, ApiResponse("ERROR", "An internal error occurred"))
}
}
}
```
## Testing Strategies and Coverage Requirements
### Test Coverage Requirements
- **Minimum coverage**: 80% overall code coverage required
- **Critical components**: 90%+ coverage for repositories, services, and validation
- **Test all edge cases**: Empty collections, null values, boundary conditions
- **Test failure paths**: Exception handling, validation errors, timeouts
- **All public APIs**: Must have integration tests
- **Performance-critical paths**: Must have benchmarking tests
### Unit Testing with Kotest
```kotlin
class UserServiceTest : DescribeSpec({
describe("UserService") {
val mockRepository = mockk<UserRepository>()
val userService = UserServiceImpl(mockRepository)
it("should return user when exists") {
val userId = UUID.randomUUID()
val user = UserDTO(userId.toString(), "Test User", "test@example.com")
coEvery { mockRepository.findById(userId) } returns user
val result = runBlocking { userService.getUserById(userId) }
result shouldBe user
}
it("should throw exception when user not found") {
val userId = UUID.randomUUID()
coEvery { mockRepository.findById(userId) } returns null
shouldThrow<ResourceNotFoundException> {
runBlocking { userService.getUserById(userId) }
}
}
}
})
```
## Route Testing with Ktor 3.x
```kotlin
class UserRoutesTest : FunSpec({
test("GET /api/users/{id} returns 200 when user exists") {
val mockService = mockk<UserService>()
val userId = UUID.randomUUID()
val user = UserDTO(userId.toString(), "Test User", "test@example.com")
coEvery { mockService.getUserById(userId) } returns user
testApplication {
application {
configureRouting()
configureDI { single { mockService } }
}
client.get("/api/users/$userId").apply {
status shouldBe HttpStatusCode.OK
bodyAsText().let {
Json.decodeFromString<ApiResponse<UserDTO>>(it)
}.data shouldBe user
}
}
}
})
```
## Key Principles for Testable Code
1. **Single Responsibility**: Each method should do one thing well
2. **Pure Functions**: Same input always produces same output
3. **Dependency Injection**: Constructor injection for testable components
4. **Clear Boundaries**: Well-defined inputs and outputs
5. **Small Methods**: Extract complex logic into testable helper functions
## Configuration Management
```kotlin
// Type-safe configuration
interface AppConfig {
val database: DatabaseConfig
val security: SecurityConfig
}
data class DatabaseConfig(
val driver: String,
val url: String,
val user: String,
val password: String
)
// Access in application
fun Application.configureDI() {
val appConfig = HoconAppConfig(environment.config)
install(Koin) {
modules(module {
single<AppConfig> { appConfig }
single { appConfig.database }
})
}
}
```
## Security Best Practices
```kotlin
fun Application.configureSecurity() {
install(Authentication) {
jwt("auth-jwt") {
// JWT configuration
}
}
install(DefaultHeaders) {
header(HttpHeaders.XContentTypeOptions, "nosniff")
header(HttpHeaders.XFrameOptions, "DENY")
header(HttpHeaders.ContentSecurityPolicy, "default-src 'self'")
header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
}
}
```
## Health Checks & Monitoring
```kotlin
fun Application.configureMonitoring() {
val startTime = System.currentTimeMillis()
routing {
get("/health") {
call.respond(mapOf("status" to "UP", "uptime" to "${(System.currentTimeMillis() - startTime) / 1000}s"))
}
get("/metrics") {
call.respond(prometheusRegistry.scrape())
}
}
install(MicrometerMetrics) {
registry = PrometheusMeterRegistry(PrometheusConfig.DEFAULT)
meterBinders = listOf(
JvmMemoryMetrics(),
JvmGcMetrics(),
ProcessorMetrics(),
JvmThreadMetrics()
)
}
}
```
## Performance Tuning
- **JVM Settings**: `-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:MaxRAMPercentage=75.0`
- **Connection Pooling**: Configure HikariCP with proper sizing based on workload
- **Caching**: Use Caffeine for in-memory caching of frequently accessed data
- **Coroutines**: Use structured concurrency for asynchronous processing
- **Database Queries**: Optimize with proper indexing, batch operations, paginationš” Suggested Test Inputs
Loading suggested inputs...
šÆ Community Test Results
Loading results...
š¦ Package Info
- Format
- cursor
- Type
- rule
- Category
- general
- License
- CC0-1.0