|
| 1 | +Project-specific development guidelines for simbot-codegen |
| 2 | + |
| 3 | +Last verified: 2025-08-08 (local), Gradle 8.10.2, Kotlin 2.2.20-Beta1 |
| 4 | + |
| 5 | +Overview |
| 6 | +- This repo is a Kotlin Multiplatform (KMP) workspace primarily targeting Web (JS + Wasm/JS) with Compose Multiplatform for the UI. |
| 7 | +- Modules: |
| 8 | + - composeApp: Web UI and code generation front-end (Wasm/JS executable). |
| 9 | + - common: Shared code and small utilities (JS + Wasm/JS libraries). |
| 10 | + - file-saver-kotlin: Minimal wrapper around the NPM `file-saver` package for Web downloads (JS + Wasm/JS). |
| 11 | + - jszip-kotlin: Wrapper for `jszip` (optional; not included by default in settings.gradle.kts). |
| 12 | +- Tooling and versions are pinned via gradle/libs.versions.toml; Kotlin wrappers catalog is pulled in settings.gradle.kts. |
| 13 | + |
| 14 | +Build and configuration notes |
| 15 | +- Gradle and JDK |
| 16 | + - Verified with Gradle wrapper 8.10.2 and Azul JDK 24.0.1. Prefer a modern JDK (21+) when possible. |
| 17 | + - Build uses type-safe accessors and version catalogs. Do not hardcode versions; add/adjust in gradle/libs.versions.toml. |
| 18 | +- Repositories |
| 19 | + - Mirrors are configured (Tencent/Huawei) for performance. Keep these unless you have a strong reason to modify. |
| 20 | + - Snapshots repo is added only for the group `love.forte.codegentle` in the root build.gradle.kts. Retain this scoping. |
| 21 | + - Local maven repo is enabled (mavenLocal()) and a local libs repo is used in composeApp for com.squareup KotlinPoet artifacts under ./libs. |
| 22 | +- Targets and outputs |
| 23 | + - composeApp: wasmJs { browser(); binaries.executable() } with dev server static dir pointed to projectDir (helps browser debugging) and output JS name set to composeApp.js. |
| 24 | + - common, file-saver-kotlin, jszip-kotlin: js { browser() } and wasmJs { browser() } with binaries.library(). In common we also enable nodejs() for js/wasm to support Node-based tests. |
| 25 | +- Useful Gradle tasks |
| 26 | + - Run the web app (dev): `./gradlew :composeApp:wasmJsBrowserDevelopmentRun` |
| 27 | + - Assemble release bundles for libs: :<module>:jsJar, :<module>:wasmJsJar |
| 28 | + - List tasks per module: ./gradlew :<module>:tasks --all |
| 29 | +- Update Lock files |
| 30 | + - Run: `gradle kotlinUpgradeYarnLock kotlinWasmUpgradeYarnLock -i` |
| 31 | + |
| 32 | +Node, NPM, and Yarn lock specifics |
| 33 | +- Kotlin/JS plugin manages Node/Yarn automatically (see tasks: kotlinNodeJsSetup, kotlinWasmNodeJsSetup). |
| 34 | +- The Yarn lock is stored under kotlin-js-store. When Kotlin or wrappers versions move, you may see: |
| 35 | + - Error: "Lock file was changed. Run the `kotlinUpgradeYarnLock` task to actualize lock file" |
| 36 | + - Fix: ./gradlew kotlinUpgradeYarnLock |
| 37 | +- You may see "Ignored scripts due to flag" during npm/yarn steps; this is expected with the Kotlin/JS toolchain. |
| 38 | + |
| 39 | +Testing: how to enable and run |
| 40 | +- Framework |
| 41 | + - Use kotlin.test (libs.kotlin.test from version catalog). Tests can be placed in commonTest or platform test source sets (jsTest, wasmJsTest) of a given module. |
| 42 | +- Enabling tests in a module |
| 43 | + - Add to the module’s build.gradle.kts inside sourceSets: commonTest.dependencies { implementation(libs.kotlin.test) } |
| 44 | + - For Node-based test tasks (fast CI-friendly), ensure the target also declares nodejs(). Example (present in :common): |
| 45 | + js { browser(); nodejs() } |
| 46 | + wasmJs { browser(); nodejs() } |
| 47 | +- Available verification tasks (module-specific) |
| 48 | + - :<module>:jsNodeTest — Run JS tests in Node. |
| 49 | + - :<module>:wasmJsNodeTest — Run Wasm/JS tests in Node. |
| 50 | + - :<module>:jsBrowserTest — Run JS tests in a browser via Karma/Webpack (requires a local browser/headless setup). |
| 51 | + - :<module>:wasmJsBrowserTest — Run Wasm/JS tests in a browser via Karma/Webpack. |
| 52 | + |
| 53 | +Demonstrated test run (validated locally) |
| 54 | +- Context |
| 55 | + - Module: :common |
| 56 | + - Source set: common/src/commonTest |
| 57 | + - Example test (kotlin.test): |
| 58 | + package love.forte.simbot.codegen |
| 59 | + |
| 60 | + import kotlin.test.Test |
| 61 | + import kotlin.test.assertEquals |
| 62 | + import kotlin.test.assertTrue |
| 63 | + |
| 64 | + class SanityTest { |
| 65 | + @Test fun addition() { assertEquals(4, 2 + 2) } |
| 66 | + @Test fun truth() { assertTrue(1 in 0..2) } |
| 67 | + } |
| 68 | +- Commands executed and outcomes |
| 69 | + 1) First run emitted a lock warning; we updated the yarn lock: |
| 70 | + ./gradlew kotlinUpgradeYarnLock |
| 71 | + 2) JS tests in Node (success): |
| 72 | + ./gradlew :common:jsNodeTest |
| 73 | + -> BUILD SUCCESSFUL |
| 74 | + 3) Wasm/JS tests in Node (success): |
| 75 | + ./gradlew :common:wasmJsNodeTest |
| 76 | + -> BUILD SUCCESSFUL |
| 77 | +- The sample test file was created only to validate the process and has been removed afterward to keep the repo clean. |
| 78 | + |
| 79 | +Guidelines for adding new tests |
| 80 | +- Prefer placing cross-platform tests into commonTest using kotlin.test. |
| 81 | +- If a module lacks kotlin.test, add it to commonTest (or jsTest/wasmJsTest as needed) in build.gradle.kts using libs.kotlin.test. |
| 82 | +- If you need Node-based test execution for a module, add nodejs() to the module’s js and/or wasmJs targets. |
| 83 | +- Typical flows: |
| 84 | + - All tests for a module: ./gradlew :<module>:allTests |
| 85 | + - Only JS/Node: ./gradlew :<module>:jsNodeTest |
| 86 | + - Only Wasm/Node: ./gradlew :<module>:wasmJsNodeTest |
| 87 | + - Browser-based JS/Wasm: use jsBrowserTest/wasmJsBrowserTest (ensure a browser/pre-requisites are available). |
| 88 | + |
| 89 | +Code style and other dev notes |
| 90 | +- Kotlin code style is set to official (gradle.properties: kotlin.code.style=official). |
| 91 | +- Keep freeCompilerArgs configured in modules unless you know why you change them: |
| 92 | + - composeApp uses -Xcontext-parameters; common uses -Xexpect-actual-classes. |
| 93 | +- composeApp webpack dev server statically serves projectDir to allow in-browser source debugging; maintain that when tweaking webpack config. |
| 94 | +- Library dependencies: |
| 95 | + - composeApp uses KotlinPoet and CodeGentle. KotlinPoet artifacts are resolved via a local ./libs repo declared in composeApp/build.gradle.kts. Do not remove unless you fully switch to maven artifacts. |
| 96 | + - file-saver-kotlin wraps NPM `file-saver`; jszip-kotlin wraps NPM `jszip`. Ensure NPM deps stay compatible with Kotlin wrappers in libs.versions.toml. |
| 97 | + |
| 98 | +Troubleshooting |
| 99 | +- Lock file changed -> run: ./gradlew kotlinUpgradeYarnLock |
| 100 | +- Node or Binaryen bootstrap errors -> run: ./gradlew kotlinNodeJsSetup kotlinWasmNodeJsSetup kotlinWasmBinaryenSetup |
| 101 | +- If browser tests fail due to missing browser, prefer Node-based test tasks (:jsNodeTest/:wasmJsNodeTest) for quick feedback. |
| 102 | + |
| 103 | +Release and publishing (internal) |
| 104 | +- Snapshots under group love.forte.codegentle are consumed from Sonatype snapshots; treat them as evolving APIs. |
| 105 | + |
| 106 | +Notes |
| 107 | +- The validated commands and behavior above were verified on 2025-08-08. If toolchain versions change, re-run kotlinUpgradeYarnLock and prefer Node-based tests for the first smoke check. |
0 commit comments