mcpField
K
kotlin-patterns

kotlin-patterns

github.com/ashchupliakDevelopment542 installsUpdated 47w ago
Repository

About kotlin-patterns

kotlin-patterns is a reference for Kotlin coding patterns used in Orca projects. It covers common server-side structures, exception handling, and null-safety conventions for developers working in that codebase.

Key features

  1. 01Entity and DTO patterns
  2. 02Service and repository patterns
  3. 03Controller and API interface patterns
  4. 04Typed exception handling
  5. 05Kotlin null-safety guidelines

Use cases

  1. 01Add entities and API endpoints
  2. 02Implement service and repository logic
  3. 03Handle validation and exceptions consistently
  4. 04Write null-safe Kotlin code

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ashchupliak/dream-team --skill kotlin-patterns

After installing, type/kotlin-patternsin Claude Code to confirm it loaded.

Details

From the project README

Kotlin Patterns for Orca

Entity Pattern

data class EntityName(
    val id: UUID,
    val name: String,
    val createdAt: Instant,
    val updatedAt: Instant?
)

Service Pattern

@Service
class EntityNameService(
    private val repository: EntityNameRepository,
    private val relatedService: RelatedService
) {
    @Transactional(propagation = Propagation.NEVER)
    fun create(request: CreateRequest): Pair<EntityResponse, Boolean> {
        // Check exists, validate, create
        // Return Pair for idempotent operations
    }

    fun findById(id: UUID): EntityName? =
        repository.findById(id)

    fun findAll(): List<EntityName> =
        repository.findAll()
}

Repository Pattern (JOOQ)

@Repository
class EntityNameRepository(
    private val dsl: DSLContext
) {
    fun findById(id: UUID): EntityName? =
        dsl.selectFrom(ENTITY_NAME)
            .where(ENTITY_NAME.ID.eq(id))
            .fetchOne()
            ?.toEntity()

    fun findAll(): List<EntityName> =
        dsl.selectFrom(ENTITY_NAME)
            .fetch()
            .map { it.toEntity() }

    fun save(entity: EntityName): EntityName =
        dsl.insertInto(ENTITY_NAME)
            .set(ENTITY_NAME.ID, entity.id)
            .set(ENTITY_NAME.NAME, entity.name)
            .set(ENTITY_NAME.CREATED_AT, entity.createdAt)
            .returning()
            .fetchOne()!!
            .toEntity()

    private fun EntityNameRecord.toEntity() = EntityName(
        id = id,
        name = name,
        createdAt = createdAt,
        updatedAt = updatedAt
    )
}

Controller Pattern

@RestController
class EntityNameController(
    private val service: EntityNameService
) : EntityNameApi {

    override fun create(request: CreateRequest): ResponseEntity<EntityResponse> {
        val (result, isNew) = service.create(request)
        return if (isNew) ResponseEntity.status(201).body(result)
        else ResponseEntity.ok(result)
    }

    override fun getById(id: UUID): ResponseEntity<EntityResponse> {
        val entity = service.findById(id)
            ?: throw ResourceNotFoundRestException("EntityName", id)
        return ResponseEntity.ok(entity.toResponse())
    }
}

API Interface Pattern

@Tag(name = "Entity Name")
interface EntityNameApi {

    @Operation(summary = "Create entity")
    @PostMapping("/api/v1/entities")
    fun create(@RequestBody @Valid request: CreateRequest): ResponseEntity<EntityResponse>

    @Operation(summary = "Get entity by ID")
    @GetMapping("/api/v1/entities/{id}")
    fun getById(@PathVariable id: UUID): ResponseEntity<EntityResponse>
}

DTO Pattern

data class CreateRequest(
    @field:NotBlank
    val name: String,

    @field:Size(max = 255)
    val description: String?
)

data class EntityResponse(
    val id: UUID,
    val name: String,
    val description: String?,
    val createdAt: Instant
)

Exception Pattern

// Use typed exceptions
throw ResourceNotFoundRestException("EntityName", id)
throw ValidationRestException("Name cannot be empty")
throw ConflictRestException("Entity already exists")

Null Safety Guidelines

  • Use ?.let{} for optional operations
  • Use when for exhaustive matching
  • Avoid !! - use .single(), .firstOrNull() instead
  • Return Pair<Result, Boolean> for idempotent operations

Comments

Markdown supported