initial skills

This commit is contained in:
nrobi144
2025-12-30 15:18:48 +02:00
parent 258c4e0111
commit f654af9d8a
23 changed files with 10898 additions and 0 deletions
@@ -0,0 +1,332 @@
# Source Set Hierarchy in Amethyst
Visual guide to source set organization with concrete examples from the codebase.
## Hierarchy Diagram
```
┌─────────────────────────────────────────────────────────────┐
│ commonMain │
│ Pure Kotlin, no platform APIs │
│ Examples: │
│ - Nostr event parsing (TextNoteEvent, MetadataEvent) │
│ - Business logic (data validation, crypto algorithms) │
│ - Data models (@Immutable data classes) │
│ Dependencies: kotlin-stdlib, kotlinx-coroutines │
└──────────────────────┬──────────────────────────────────────┘
┌────────────┴────────────┬───────────────┐
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌───────────────────┐ ┌──────────────┐
│ jvmAndroid │ │ iosMain │ │ Future: │
│ JVM libraries │ │ iOS common │ │ jsMain │
│ Examples: │ │ Examples: │ │ wasmMain │
│ - Jackson JSON │ │ - Platform API │ └──────────────┘
│ - OkHttp HTTP │ │ - Actuals for │
│ - url-detector │ │ crypto/I/O │
│ Dependencies: │ │ Dependencies: │
│ - Jackson │ │ - Platform libs │
│ - OkHttp │ └───────┬───────────┘
└────┬─────────┬───┘ │
│ │ ├─→ iosX64Main (simulator Intel)
│ │ ├─→ iosArm64Main (device ARM64)
│ │ └─→ iosSimulatorArm64Main (Apple Silicon)
▼ ▼
┌──────────┐ ┌───────────┐
│android │ │ jvmMain │
│Main │ │ (Desktop) │
│Examples: │ │ Examples: │
│- Activity│ │- Window │
│- ViewModel│ │- MenuBar │
│- Android │ │- Desktop │
│ APIs │ │ Compose │
│Deps: │ │ Deps: │
│- secp256k│ │- secp256k │
│ 1-android│ │ 1-jvm │
│- androidx│ │- Compose │
│ │ │ Desktop │
└──────────┘ └───────────┘
```
## Dependency Flow
```
Code in commonMain
↓ can use
Nothing (only Kotlin stdlib)
Code in jvmAndroid
↓ can use
commonMain + JVM libraries (Jackson, OkHttp)
Code in androidMain
↓ can use
commonMain + jvmAndroid + Android framework
Code in jvmMain
↓ can use
commonMain + jvmAndroid + JVM + Compose Desktop
Code in iosMain
↓ can use
commonMain + iOS platform APIs
```
## Real Examples from Amethyst
### commonMain - Pure Kotlin
**File:** `quartz/src/commonMain/.../TextNoteEvent.kt`
```kotlin
@Immutable
class TextNoteEvent(
id: HexKey,
pubKey: HexKey,
createdAt: Long,
tags: Array<Array<String>>,
content: String,
sig: HexKey,
) : BaseThreadedEvent(...) {
// Pure Kotlin - works everywhere
override fun indexableContent() = "Subject: " + subject() + "\n" + content
}
```
**Why commonMain:**
- Pure Kotlin code
- No platform APIs
- Data class with business logic
- Needed by all platforms
---
### jvmAndroid - JVM Libraries
**File:** `quartz/build.gradle.kts`
```kotlin
val jvmAndroid = create("jvmAndroid") {
dependsOn(commonMain.get())
dependencies {
// Normalizes URLs
api(libs.rfc3986.normalizer)
// Performant Parser of JSONs into Events
api(libs.jackson.module.kotlin)
// Parses URLs from Text
api(libs.url.detector)
// Websockets API
implementation(libs.okhttp)
implementation(libs.okhttpCoroutines)
}
}
jvmMain { dependsOn(jvmAndroid) } // Desktop gets Jackson, OkHttp
androidMain { dependsOn(jvmAndroid) } // Android gets Jackson, OkHttp
```
**Why jvmAndroid:**
- Jackson, OkHttp are JVM-only libraries
- Works on Android (JVM) and Desktop (JVM)
- Does NOT work on iOS (not JVM) or web (not JVM)
**Usage in code:**
```kotlin
// Can use Jackson in jvmAndroid source set
val mapper = ObjectMapper()
val event = mapper.readValue(json, Event::class.java)
```
---
### androidMain - Android Platform
**File:** `amethyst/src/main/.../MainActivity.kt`
```kotlin
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge() // Android API
super.onCreate(savedInstanceState)
setContent { // Compose for Android
AmethystTheme {
val accountStateViewModel: AccountStateViewModel = viewModel()
AccountScreen(accountStateViewModel)
}
}
}
}
```
**Why androidMain:**
- AppCompatActivity is Android framework
- Activity lifecycle Android-specific
- AndroidX libraries (viewModel())
**Dependencies:**
```kotlin
androidMain {
dependsOn(jvmAndroid) // Gets Jackson, OkHttp
dependencies {
implementation(libs.androidx.core.ktx)
api(libs.secp256k1.kmp.jni.android) // Android crypto
}
}
```
---
### jvmMain - Desktop Platform
**File:** `desktopApp/src/jvmMain/.../Main.kt`
```kotlin
fun main() = application {
val windowState = rememberWindowState(
width = 1200.dp,
height = 800.dp
)
Window( // Compose Desktop API
onCloseRequest = ::exitApplication,
state = windowState,
title = "Amethyst"
) {
MenuBar { // Desktop-specific
Menu("File") {
Item("New Note", shortcut = KeyShortcut(Key.N, ctrl = true))
}
}
NavigationRail { ... } // Sidebar
}
}
```
**Why jvmMain:**
- Window, MenuBar, NavigationRail are Compose Desktop
- Keyboard shortcuts desktop paradigm
- Different UX from Android (sidebar vs bottom nav)
**Dependencies:**
```kotlin
jvmMain {
dependsOn(jvmAndroid) // Gets Jackson, OkHttp
dependencies {
implementation(libs.secp256k1.kmp.jni.jvm) // Desktop crypto
implementation(compose.desktop.currentOs)
}
}
```
---
### iosMain - iOS Platform
**File:** `quartz/build.gradle.kts`
```kotlin
iosMain {
dependsOn(commonMain.get())
dependencies {
// iOS platform dependencies
}
}
val iosX64Main by getting { dependsOn(iosMain.get()) }
val iosArm64Main by getting { dependsOn(iosMain.get()) }
val iosSimulatorArm64Main by getting { dependsOn(iosMain.get()) }
```
**Why iosMain:**
- iOS platform APIs
- Native crypto (Security framework)
- Different from Android/Desktop
**Architecture targets:**
- iosX64Main: Intel simulator
- iosArm64Main: Device (iPhone, iPad)
- iosSimulatorArm64Main: Apple Silicon simulator
---
## Build Order Matters
**CRITICAL:** jvmAndroid must be defined BEFORE androidMain and jvmMain:
```kotlin
// ✅ CORRECT ORDER
val jvmAndroid = create("jvmAndroid") { ... }
jvmMain { dependsOn(jvmAndroid) }
androidMain { dependsOn(jvmAndroid) }
// ❌ WRONG - Build error
androidMain { dependsOn(jvmAndroid) } // jvmAndroid not defined yet!
val jvmAndroid = create("jvmAndroid") { ... }
```
See comment in quartz/build.gradle.kts:131:
```kotlin
// Must be defined before androidMain and jvmMain
val jvmAndroid = create("jvmAndroid") { ... }
```
## Choosing the Right Source Set
Decision flowchart:
```
Q: Where should this code go?
├─ Pure Kotlin? (no platform APIs)
│ └─ commonMain
├─ JVM library? (Jackson, OkHttp)
│ └─ jvmAndroid
├─ Android API? (Activity, Context)
│ └─ androidMain
├─ Desktop API? (Window, MenuBar)
│ └─ jvmMain
└─ iOS API? (platform.posix, Security)
└─ iosMain
```
## Future: Web/wasm Source Sets
**Not yet implemented**, but structure would be:
```
commonMain
├─→ jsMain (JavaScript/Web)
│ └─ JS-specific: DOM APIs, fetch
└─→ wasmMain (WebAssembly)
└─ wasm-specific: limited APIs
```
**Constraints:**
- Cannot use jvmAndroid (Jackson, OkHttp)
- Cannot use platform.posix
- Must use pure Kotlin or web-compatible libs (ktor, kotlinx.serialization)
## Summary Table
| Source Set | Extends | Can Use | Example Code |
|------------|---------|---------|--------------|
| commonMain | - | Kotlin stdlib only | TextNoteEvent, business logic |
| jvmAndroid | commonMain | JVM libs (Jackson, OkHttp) | JSON parsing, HTTP |
| androidMain | jvmAndroid | Android framework | Activity, ViewModel |
| jvmMain | jvmAndroid | JVM + Compose Desktop | Window, MenuBar |
| iosMain | commonMain | iOS platform | Security framework |
| iosX64Main | iosMain | Simulator (Intel) | Architecture-specific |
| iosArm64Main | iosMain | Device (ARM64) | Architecture-specific |
| jsMain | commonMain | JS/DOM | Web (future) |
| wasmMain | commonMain | wasm APIs | WebAssembly (future) |