Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

As an AI agent, your primary directive is to adhere to the established patterns, API contracts, and modular architecture of **Shikkanime Framework**. Your goal is to write clean, maintainable, and secure framework components in Kotlin that align with the existing codebase.

This file contains your core, non-negotiable root rules (règles mère). For detailed framework implementation guidance, refer to the linked documents in the `guidelines` directory as well as submodule-specific rules in each subfolder (`core/AGENTS.md`, `cache/AGENTS.md`, `exposed/AGENTS.md`, `validator/AGENTS.md`, `ktor/AGENTS.md`).
This file contains your core, non-negotiable root rules. For detailed framework implementation guidance, refer to the linked documents in the `guidelines` directory as well as submodule-specific rules in each subfolder (`core/AGENTS.md`, `cache/AGENTS.md`, `exposed/AGENTS.md`, `validator/AGENTS.md`, `ktor/AGENTS.md`, `plugin/AGENTS.md`).

## 1. The Prime Directive: Respect Framework Architecture & Module Boundaries

The project is structured into distinct, decoupled framework modules. **Do not violate module boundaries or introduce circular dependencies.**

- **Dependencies Flow:** `core` (standalone) <- `cache`, `exposed` & `validator` <- `ktor`
- **Dependencies Flow:** `core` (standalone) <- `cache`, `exposed` & `validator` <- `ktor` ; `plugin` (Gradle convention plugins)
- **`core`**: Base logging (`LoggerFactory`), utilities. MUST remain zero-dependency relative to other submodules.
- **`cache`**: Two-level caching engine (`Cache`), L1 LRU memory cache (`L1Cache`), L2 Valkey client (`ValkeyWrapper`), CBOR binary serialization (`BinaryCodec`), bucket versioning, and single-flight loader deduplication (`SingleFlight`).
- **`exposed`**: Database connection management (`DatabaseWrapper`), Exposed ORM integration, Liquibase migrations, `@Transactional` annotations & proxying (`TransactionalProxy`), and repository base classes (`AbstractRepository`).
- **`validator`**: Reflection-based validation engine (`Validator`), constraints (`@RequireAtLeastOneValid`, `@NotNull`, `@NotBlank`, `@NotEmpty`), and `ObjectNotValidException`.
- **`ktor`**: Ktor (server and client) integrations, route annotation binding (`@RestController`, `@GetMapping`, `@PostMapping`, `@PatchMapping`), request parameter resolvers (`@QueryParam`, `@PathParam`, `@RequestBody`), automatic `@Valid` validation integration, `ResponseEntity` wrapper, `MessageDto` error response standardization, OpenAPI metadata (`@Operation`, `@ApiResponses`, `@ApiResponse`), and a preconfigured HTTP client (`createHttpClient`).
- **`plugin`**: Gradle convention plugins for downstream projects (e.g. `fr.shikkanime.framework.ktor`).

For detailed architectural principles, read the [Architecture Guide](guidelines/ARCHITECTURE.md).

Expand All @@ -40,14 +41,15 @@ Refer to the style, convention, and testing guides:
- [Cache Guide](guidelines/CACHE.md)
- [Testing Guide](guidelines/TESTING.md)

## 4. Submodule Rules (Règles par Sous-Module)
## 4. Submodule Rules

Each framework module has its own dedicated `AGENTS.md` specifying module-specific constraints and responsibilities:
- [`core/AGENTS.md`](core/AGENTS.md): Core utilities & custom logging system.
- [`cache/AGENTS.md`](cache/AGENTS.md): Two-level caching facade, Valkey wrapper, CBOR codec, and single-flight deduplication.
- [`exposed/AGENTS.md`](exposed/AGENTS.md): Database wrappers, transaction management, Liquibase, and repository upsert DSL.
- [`validator/AGENTS.md`](validator/AGENTS.md): Annotation-based reflection validator and custom constraints.
- [`ktor/AGENTS.md`](ktor/AGENTS.md): Controller binding, HTTP argument resolution, response wrappers, and OpenAPI doc generation.
- [`plugin/AGENTS.md`](plugin/AGENTS.md): Gradle convention plugins for downstream projects.

## 5. Before Submitting Changes

Expand Down
16 changes: 12 additions & 4 deletions buildSrc/src/main/kotlin/kotlin-jvm.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package buildsrc.convention
import org.gradle.api.tasks.testing.logging.TestLogEvent

group = "fr.shikkanime.framework"
version = providers.gradleProperty("version").orNull ?: "0.0.7-SNAPSHOT"
version = providers.gradleProperty("version").get()

plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin in JVM projects.
Expand All @@ -26,9 +26,11 @@ java {

publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
artifactId = project.name
if (!plugins.hasPlugin("java-gradle-plugin")) {
create<MavenPublication>("maven") {
from(components["java"])
artifactId = project.name
}
}
}
repositories {
Expand All @@ -43,6 +45,12 @@ publishing {
}
}

tasks.withType<Jar>().configureEach {
manifest {
attributes["Implementation-Version"] = project.version
}
}

tasks.withType<Test>().configureEach {
// Configure all test Gradle tasks to use JUnitPlatform.
useJUnitPlatform()
Expand Down
2 changes: 1 addition & 1 deletion cache/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file contains specific rules for the `cache` submodule. All agents working
## Module Purpose & Scope
The `cache` module provides a two-level caching engine combining an in-memory L1 LRU cache (`L1Cache`), a distributed L2 Valkey/Redis client wrapper (`ValkeyWrapper`), CBOR binary serialization (`BinaryCodec`), bucket versioning, and single-flight loader deduplication (`SingleFlight`).

## Submodule-Specific Rules (Règles du sous-module)
## Submodule-Specific Rules

1. **Module Hierarchy & Dependencies**:
- `cache` depends on `core`. It MUST NOT depend on `exposed`, `validator`, or `ktor`.
Expand Down
2 changes: 1 addition & 1 deletion core/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file contains specific rules for the `core` submodule. All agents working w
## Module Purpose & Scope
The `core` module provides foundational utilities and logging capabilities for the Shikkanime framework, primarily centered around `LoggerFactory` and `LogFormatter`.

## Submodule-Specific Rules (Règles du sous-module)
## Submodule-Specific Rules

1. **Zero Framework Dependencies**:
- `core` MUST NOT depend on `exposed`, `validator`, `ktor`, or any other submodule.
Expand Down
2 changes: 1 addition & 1 deletion exposed/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file contains specific rules for the `exposed` submodule. All agents workin
## Module Purpose & Scope
The `exposed` module handles database persistence, connection pooling (`HikariCP`), schema migrations (`Liquibase`), Exposed ORM integration, transaction management (`@Transactional` & `TransactionalProxy`), and repository base classes (`AbstractRepository`).

## Submodule-Specific Rules (Règles du sous-module)
## Submodule-Specific Rules

1. **Module Hierarchy & Dependencies**:
- `exposed` depends on `core`. It MUST NOT depend on `validator` or `ktor`.
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mockk = "1.14.11"

[libraries]
kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
ktorGradlePlugin = { module = "io.ktor.plugin:io.ktor.plugin.gradle.plugin", version.ref = "ktor" }
exposedCore = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
exposedDao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
exposedJdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
Expand Down
2 changes: 1 addition & 1 deletion ktor/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file contains specific rules for the `ktor` submodule. All agents working w
## Module Purpose & Scope
The `ktor` module provides web framework integration for Ktor (server **and client**). It handles `@RestController` discovery, route mapping (`@GetMapping`, `@PostMapping`, `@PatchMapping`), request argument resolution (`@QueryParam`, `@PathParam`, `@RequestBody`), automatic `@Valid` validation, `ResponseEntity` packaging, `MessageDto` response serialization, and OpenAPI documentation generation, as well as framework-aware HTTP clients (e.g. a preconfigured `HttpClient`).

## Submodule-Specific Rules (Règles du sous-module)
## Submodule-Specific Rules

1. **Module Hierarchy & Dependencies**:
- `ktor` depends on `core` and `validator`. It MUST NOT depend on `exposed`.
Expand Down
16 changes: 16 additions & 0 deletions plugin/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Module Rules: Plugin (`plugin`)

This file contains specific rules for the `plugin` submodule. All agents working within this submodule must strictly adhere to these guidelines in addition to the root [`AGENTS.md`](../AGENTS.md).

## Module Purpose & Scope
The `plugin` module provides Gradle convention plugins for downstream projects consuming **Shikkanime Framework**. It encapsulates plugin applications and version alignment (e.g., Ktor plugin integration via `fr.shikkanime.framework.ktor`).

## Submodule-Specific Rules

1. **Gradle Plugin API**:
- All convention plugins must implement `org.gradle.api.Plugin<Project>`.
- Document every public plugin class with comprehensive KDoc comments.
- Ensure plugins handle property fallbacks gracefully.

2. **Testing**:
- Every plugin must have corresponding unit tests verifying plugin application and configuration behavior using Gradle's `ProjectBuilder`.
21 changes: 21 additions & 0 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
plugins {
`java-gradle-plugin`
id("buildsrc.convention.kotlin-jvm")
}

gradlePlugin {
plugins {
create("ktorFrameworkPlugin") {
id = "fr.shikkanime.framework.ktor"
implementationClass = "fr.shikkanime.framework.plugin.KtorFrameworkPlugin"
}
}
}

dependencies {
implementation(libs.ktorGradlePlugin)

testImplementation(kotlin("test"))
testImplementation(libs.kotlinGradlePlugin)
testImplementation(libs.bundles.testEcosystem)
}
25 changes: 25 additions & 0 deletions plugin/src/main/kotlin/KtorFrameworkPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package fr.shikkanime.framework.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project

/**
* Gradle convention plugin for Ktor integration in Shikkanime Framework projects.
*
* Applies the underlying `io.ktor.plugin` and configures the target project with
* framework Ktor dependencies automatically.
*/
class KtorFrameworkPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.pluginManager.apply("io.ktor.plugin")

val frameworkVersion = KtorFrameworkPlugin::class.java.`package`.implementationVersion
?: project.providers.gradleProperty("version").orNull
?: project.findProperty("version")?.toString()
?: error("Framework version is missing. Ensure Implementation-Version in MANIFEST.MF or 'version' property in gradle.properties is configured.")

project.plugins.withId("org.jetbrains.kotlin.jvm") {
project.dependencies.add("implementation", "fr.shikkanime.framework:ktor:$frameworkVersion")
}
}
}
33 changes: 33 additions & 0 deletions plugin/src/test/kotlin/KtorFrameworkPluginTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package fr.shikkanime.framework.plugin

import org.gradle.testfixtures.ProjectBuilder
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

class KtorFrameworkPluginTest {

@Nested
@DisplayName("tests for KtorFrameworkPlugin application")
inner class ApplicationTests {

@Test
fun `should apply io ktor plugin and add framework ktor dependency`() {
// Given
val project = ProjectBuilder.builder().build()
project.version = "0.0.7-SNAPSHOT"
project.plugins.apply("org.jetbrains.kotlin.jvm")

// When
project.plugins.apply(KtorFrameworkPlugin::class.java)

// Then
assertTrue(project.plugins.hasPlugin("io.ktor.plugin"))
val hasKtorDependency = project.configurations.getByName("implementation").dependencies.any {
it.group == "fr.shikkanime.framework" && it.name == "ktor"
}
assertTrue(hasKtorDependency)
}
}
}
4 changes: 3 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ dependencyResolutionManagement {
@Suppress("UnstableApiUsage")
repositories {
mavenCentral()
gradlePluginPortal()
}
}

Expand All @@ -16,5 +17,6 @@ include(
":exposed",
":validator",
":ktor",
":cache"
":cache",
":plugin"
)
2 changes: 1 addition & 1 deletion validator/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This file contains specific rules for the `validator` submodule. All agents work
## Module Purpose & Scope
The `validator` module provides a lightweight, reflection-based validation engine (`Validator`), standard validation annotations (`@RequireAtLeastOneValid`, `@NotNull`, `@NotBlank`, `@NotEmpty`), and the `ObjectNotValidException` error.

## Submodule-Specific Rules (Règles du sous-module)
## Submodule-Specific Rules

1. **Module Hierarchy & Dependencies**:
- `validator` requires Kotlin reflection (`kotlin-reflect`). It MUST NOT depend on `exposed` or `ktor`.
Expand Down
Loading