create-ait-cmp-app 0.0.0-stage → 1.0.0-alpha01

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +31 -2
  2. package/cli.js +268 -0
  3. package/package.json +29 -3
  4. package/templates/app/.editorconfig +15 -0
  5. package/templates/app/LICENSE +21 -0
  6. package/templates/app/README.md +25 -0
  7. package/templates/app/_github/workflows/ci.yml +56 -0
  8. package/templates/app/_gitignore +11 -0
  9. package/templates/app/_yarn.lock +2560 -0
  10. package/templates/app/_yarnrc.yml +1 -0
  11. package/templates/app/androidApp/README.md +19 -0
  12. package/templates/app/androidApp/build.gradle.kts +29 -0
  13. package/templates/app/androidApp/src/main/AndroidManifest.xml +15 -0
  14. package/templates/app/androidApp/src/main/kotlin/io/github/l2hyunwoo/ait/sample/android/MainActivity.kt +49 -0
  15. package/templates/app/apps-in-toss.config.ts +2 -0
  16. package/templates/app/appsInTossApp/README.md +23 -0
  17. package/templates/app/appsInTossApp/build.gradle.kts +34 -0
  18. package/templates/app/appsInTossApp/src/webMain/kotlin/BrowserDraftStorage.kt +9 -0
  19. package/templates/app/appsInTossApp/src/webMain/kotlin/Main.kt +68 -0
  20. package/templates/app/appsInTossApp/src/webMain/resources/index.html +4 -0
  21. package/templates/app/build.gradle.kts +37 -0
  22. package/templates/app/docs/development.md +56 -0
  23. package/templates/app/eslint.config.mjs +19 -0
  24. package/templates/app/gradle/libs.versions.toml +31 -0
  25. package/templates/app/gradle/wrapper/gradle-wrapper.jar +0 -0
  26. package/templates/app/gradle/wrapper/gradle-wrapper.properties +10 -0
  27. package/templates/app/gradle.properties +3 -0
  28. package/templates/app/gradlew +248 -0
  29. package/templates/app/gradlew.bat +112 -0
  30. package/templates/app/iosApp/README.md +17 -0
  31. package/templates/app/iosApp/ServiceSample.xcodeproj/project.pbxproj +323 -0
  32. package/templates/app/iosApp/ServiceSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  33. package/templates/app/iosApp/ServiceSample.xcodeproj/xcshareddata/xcschemes/ServiceSample.xcscheme +91 -0
  34. package/templates/app/iosApp/iosApp/ServiceSampleApp.swift +20 -0
  35. package/templates/app/licenses/NotoSansKR-OFL.txt +93 -0
  36. package/templates/app/package.json +31 -0
  37. package/templates/app/scripts/lint-kotlin.mjs +8 -0
  38. package/templates/app/scripts/web.mjs +52 -0
  39. package/templates/app/settings.gradle.kts +17 -0
  40. package/templates/app/shared-core/README.md +19 -0
  41. package/templates/app/shared-core/build.gradle.kts +37 -0
  42. package/templates/app/shared-core/src/commonMain/kotlin/io/github/l2hyunwoo/ait/sample/Notes.kt +37 -0
  43. package/templates/app/shared-core/src/commonTest/kotlin/io/github/l2hyunwoo/ait/sample/NotesApiClientTest.kt +17 -0
  44. package/templates/app/shared-core/src/jsMain/kotlin/io/github/l2hyunwoo/ait/sample/BrowserNote.kt +12 -0
  45. package/templates/app/shared-ui/README.md +22 -0
  46. package/templates/app/shared-ui/build.gradle.kts +49 -0
  47. package/templates/app/shared-ui/src/commonMain/composeResources/files/NotoSansKR-OFL.txt +93 -0
  48. package/templates/app/shared-ui/src/commonMain/composeResources/font/NotoSansKR.ttf +0 -0
  49. package/templates/app/shared-ui/src/commonMain/kotlin/io/github/l2hyunwoo/ait/sample/ServiceApp.kt +121 -0
  50. package/templates/app/shared-ui/src/iosMain/kotlin/io/github/l2hyunwoo/ait/sample/MainViewController.kt +40 -0
  51. package/templates/app/webApp/README.md +18 -0
  52. package/templates/app/webApp/build.gradle.kts +23 -0
  53. package/templates/app/webApp/src/webMain/kotlin/BrowserDraftStorage.kt +9 -0
  54. package/templates/app/webApp/src/webMain/kotlin/Main.kt +8 -0
  55. package/templates/app/webApp/src/webMain/resources/index.html +4 -0
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
@@ -0,0 +1,19 @@
1
+ # Android 메모 앱
2
+
3
+ [공통 UI](../shared-ui/README.md)의 `ServiceApp()`을 Android Activity에서 실행하는 앱입니다. 토스 SDK·TDS·토스 mock을 설치하지 않습니다.
4
+
5
+ ## Android 연결
6
+
7
+ 메모 초안을 SharedPreferences에 저장하고, 공유 버튼은 Android 공유 선택창을 엽니다. 상세 화면의 시스템 뒤로 가기는 목록으로 돌아가며 목록의 뒤로 가기는 Activity 종료 동작을 따릅니다. Activity 재생성 시 선택한 메모를 복원합니다.
8
+
9
+ 저장은 메모 ID를 기준으로 하며 계정별 분리·암호화·서버 동기화는 포함하지 않습니다. 앱 데이터를 삭제하면 저장한 초안도 삭제됩니다.
10
+
11
+ ## 실행
12
+
13
+ JDK 17과 Android SDK 37을 준비하고 프로젝트 루트에서 빌드합니다.
14
+
15
+ ```sh
16
+ ./gradlew :androidApp:assembleDebug
17
+ ```
18
+
19
+ Android Studio에서 프로젝트 루트를 열고 Android 7.0(API 24) 이상 기기에 실행합니다. 시작점은 [MainActivity](src/main/kotlin/io/github/l2hyunwoo/ait/sample/android/MainActivity.kt)입니다.
@@ -0,0 +1,29 @@
1
+ plugins {
2
+ alias(libs.plugins.android.application)
3
+ alias(libs.plugins.kotlin.compose)
4
+ }
5
+
6
+ android {
7
+ namespace = "__PACKAGE_NAME__.android"
8
+ compileSdk = libs.versions.android.compileSdk.get().toInt()
9
+
10
+ defaultConfig {
11
+ applicationId = "__PACKAGE_NAME__"
12
+ minSdk = 24
13
+ targetSdk = libs.versions.android.targetSdk.get().toInt()
14
+ versionCode = 1
15
+ versionName = "0.1.0"
16
+ }
17
+ compileOptions {
18
+ sourceCompatibility = JavaVersion.VERSION_17
19
+ targetCompatibility = JavaVersion.VERSION_17
20
+ }
21
+ buildFeatures { compose = true }
22
+ }
23
+
24
+ kotlin { compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) } }
25
+
26
+ dependencies {
27
+ implementation(project(":shared-ui"))
28
+ implementation(libs.androidx.activity.compose)
29
+ }
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <application
4
+ android:label="__DISPLAY_NAME__"
5
+ android:theme="@android:style/Theme.Material.Light.NoActionBar">
6
+ <activity
7
+ android:name=".MainActivity"
8
+ android:exported="true">
9
+ <intent-filter>
10
+ <action android:name="android.intent.action.MAIN" />
11
+ <category android:name="android.intent.category.LAUNCHER" />
12
+ </intent-filter>
13
+ </activity>
14
+ </application>
15
+ </manifest>
@@ -0,0 +1,49 @@
1
+ package __PACKAGE_NAME__.android
2
+
3
+ import android.content.Intent
4
+ import android.content.SharedPreferences
5
+ import android.os.Bundle
6
+ import androidx.activity.ComponentActivity
7
+ import androidx.activity.compose.BackHandler
8
+ import androidx.activity.compose.setContent
9
+ import androidx.activity.enableEdgeToEdge
10
+ import androidx.compose.runtime.remember
11
+ import androidx.compose.runtime.saveable.Saver
12
+ import androidx.compose.runtime.saveable.rememberSaveable
13
+ import __PACKAGE_NAME__.DraftStorage
14
+ import __PACKAGE_NAME__.ServiceApp
15
+ import __PACKAGE_NAME__.ServiceNavigation
16
+
17
+ class MainActivity : ComponentActivity() {
18
+ override fun onCreate(savedInstanceState: Bundle?) {
19
+ super.onCreate(savedInstanceState)
20
+ enableEdgeToEdge()
21
+ setContent {
22
+ val state = rememberSaveable(
23
+ saver = Saver<ServiceNavigation, List<String>>(
24
+ save = { listOfNotNull(it.selectedId) },
25
+ restore = { ServiceNavigation().apply { selectedId = it.firstOrNull() } },
26
+ ),
27
+ ) { ServiceNavigation() }
28
+ val storage = remember {
29
+ PreferencesDraftStorage(getSharedPreferences("drafts", MODE_PRIVATE))
30
+ }
31
+ BackHandler(enabled = state.selectedId != null) { state.back() }
32
+ ServiceApp(state = state, storage = storage, onShare = { text ->
33
+ val send = Intent(Intent.ACTION_SEND).apply {
34
+ type = "text/plain"
35
+ putExtra(Intent.EXTRA_TEXT, text)
36
+ }
37
+ startActivity(Intent.createChooser(send, "공유"))
38
+ })
39
+ }
40
+ }
41
+ }
42
+
43
+ private class PreferencesDraftStorage(private val preferences: SharedPreferences) : DraftStorage {
44
+ override fun read(id: String): String? = preferences.getString("draft:$id", null)
45
+
46
+ override fun write(id: String, body: String) {
47
+ preferences.edit().putString("draft:$id", body).apply()
48
+ }
49
+ }
@@ -0,0 +1,2 @@
1
+ import { defineConfig } from '@apps-in-toss/web-framework/config';
2
+ export default defineConfig({appName:"__APP_NAME__",brand:{primaryColor:"#3469D9"},permissions:[],navigationBar:{withBackButton:true,withHomeButton:true,theme:"light"},webBundleDir:"dist/apps-in-toss"});
@@ -0,0 +1,23 @@
1
+ # 앱인토스 메모 앱
2
+
3
+ 공통 메모 화면에 토스 로그인·공유·호스트 이벤트·안전 영역을 연결한 Compose 웹앱 예제입니다. 앱인토스 전용 UI와 기능을 이 호스트에 둡니다.
4
+
5
+ ## 구성과 동작
6
+
7
+ [공통 UI](../shared-ui/README.md)와 [공통 core](../shared-core/README.md)를 사용합니다. 초안은 브라우저 localStorage에 메모 ID별로 저장하며 출처(origin)별로 구분합니다. 로그인 결과는 화면 상태로 전달하며 서버의 인가 코드 교환은 구현하지 않았습니다.
8
+
9
+ 뒤로 가기 이벤트는 상세 화면에서 목록으로 이동하고 목록에서는 호스트 화면을 닫습니다. 홈 이벤트는 선택한 메모를 해제합니다. 클라이언트는 Compose 호스트가 해제될 때 닫습니다.
10
+
11
+ ## 실행
12
+
13
+ 프로젝트 루트에서 실행합니다. Node 24 이상·Corepack·JDK 17과 Yarn 의존성이 필요합니다.
14
+
15
+ ```sh
16
+ yarn dev
17
+ yarn dev:toss
18
+ yarn build
19
+ ```
20
+
21
+ `dev`는 mock, `dev:toss`는 실제 브리지로 실행합니다. `build`는 실제 브리지를 포함한 `.ait`를 만듭니다. `apps-in-toss.config.ts`의 appName·브랜드·권한 등 서비스 설정을 콘솔과 맞춰야 합니다. 자동 업로드는 하지 않습니다.
22
+
23
+ 예제 데이터와 mock 인증 결과는 운영 데이터·인증 증명이 아닙니다. TDS는 포함하지 않습니다.
@@ -0,0 +1,34 @@
1
+ plugins {
2
+ alias(libs.plugins.kotlin.multiplatform)
3
+ alias(libs.plugins.kotlin.compose)
4
+ alias(libs.plugins.compose)
5
+ }
6
+ kotlin {
7
+ js {
8
+ browser()
9
+ binaries.executable()
10
+ }
11
+ wasmJs {
12
+ browser()
13
+ binaries.executable()
14
+ }
15
+ sourceSets {
16
+ commonMain.dependencies {
17
+ implementation(project(":shared-ui"))
18
+ implementation(libs.compose.ui)
19
+ implementation(libs.compose.material3)
20
+ implementation(libs.coroutines.core)
21
+ implementation("io.github.l2hyunwoo:apps-in-toss-sdk:1.0.0-alpha01")
22
+ }
23
+ }
24
+ }
25
+
26
+ val sdkWebResources = configurations.create("sdkWebResources")
27
+ dependencies {
28
+ add(sdkWebResources.name, "io.github.l2hyunwoo:apps-in-toss-sdk:1.0.0-alpha01:web-resources@jar")
29
+ }
30
+ tasks.register<Sync>("prepareAppsInTossBridge") {
31
+ dependsOn(sdkWebResources)
32
+ from({ sdkWebResources.map { zipTree(it) } })
33
+ into(layout.buildDirectory.dir("ait-cmp-sdk"))
34
+ }
@@ -0,0 +1,9 @@
1
+ import __PACKAGE_NAME__.DraftStorage
2
+ import kotlinx.browser.window
3
+
4
+ class BrowserDraftStorage : DraftStorage {
5
+ override fun read(id: String): String? = window.localStorage.getItem("cmp-note-$id")
6
+ override fun write(id: String, body: String) {
7
+ window.localStorage.setItem("cmp-note-$id", body)
8
+ }
9
+ }
@@ -0,0 +1,68 @@
1
+ import androidx.compose.foundation.layout.*
2
+ import androidx.compose.material3.*
3
+ import androidx.compose.runtime.*
4
+ import androidx.compose.ui.ExperimentalComposeUiApi
5
+ import androidx.compose.ui.Modifier
6
+ import androidx.compose.ui.unit.dp
7
+ import androidx.compose.ui.window.ComposeViewport
8
+ import io.github.l2hyunwoo.ait.*
9
+ import __PACKAGE_NAME__.*
10
+ import kotlinx.coroutines.CancellationException
11
+ import kotlinx.coroutines.launch
12
+
13
+ @OptIn(ExperimentalComposeUiApi::class)
14
+ fun main() {
15
+ ComposeViewport(viewportContainerId = "compose-root") {
16
+ val client = remember { createAppsInTossClient() }
17
+ val scope = rememberCoroutineScope()
18
+ val navigation = remember { ServiceNavigation() }
19
+ val storage = remember { BrowserDraftStorage() }
20
+ var status by remember { mutableStateOf("앱인토스 전용 영역이에요. 현재 환경: ${client.host}") }
21
+ var insets by remember { mutableStateOf(SafeAreaInsets(0.0, 0.0, 0.0, 0.0)) }
22
+ DisposableEffect(client) { onDispose { client.close() } }
23
+ LaunchedEffect(client) {
24
+ if (client.host != RuntimeHost.BROWSER) {
25
+ try {
26
+ client.events.collect { event ->
27
+ when (event) {
28
+ is HostEvent.SafeArea -> insets = event.insets
29
+ HostEvent.Back -> if (!navigation.back()) client.closeScreen()
30
+ HostEvent.Home -> navigation.selectedId = null
31
+ }
32
+ }
33
+ } catch (e: CancellationException) {
34
+ throw e
35
+ } catch (_: Exception) {
36
+ status = "호스트 이벤트를 연결하지 못했어요."
37
+ }
38
+ }
39
+ }
40
+ Box(Modifier.padding(top = insets.top.dp, bottom = insets.bottom.dp, start = insets.left.dp, end = insets.right.dp)) {
41
+ ServiceApp(state = navigation, storage = storage, showBackButton = client.host == RuntimeHost.MOCK, onShare = { text ->
42
+ scope.launch {
43
+ try {
44
+ client.shareText(text)
45
+ } catch (e: CancellationException) {
46
+ throw e
47
+ } catch (_: Exception) {
48
+ status = "공유하지 못했어요."
49
+ }
50
+ }
51
+ }, hostContent = {
52
+ Text(status)
53
+ Button(enabled = client.supports(Capability.TOSS_LOGIN), onClick = {
54
+ scope.launch {
55
+ status = try {
56
+ client.requestTossLogin()
57
+ "인가 결과를 받았어요. 실제 서비스는 서버에서 교환해야 해요."
58
+ } catch (e: CancellationException) {
59
+ throw e
60
+ } catch (e: AppsInTossException) {
61
+ "로그인을 완료하지 못했어요: ${e.code}"
62
+ }
63
+ }
64
+ }) { Text("토스로 로그인해요") }
65
+ })
66
+ }
67
+ }
68
+ }
@@ -0,0 +1,4 @@
1
+ <!doctype html>
2
+ <html lang="ko"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>__DISPLAY_NAME__</title><style>html,body,#compose-root{margin:0;width:100%;height:100%;overflow:hidden}#error{padding:24px}</style></head>
3
+ <body><div id="compose-root"></div><div id="error" role="alert" hidden></div><script>window.addEventListener('error',()=>{const e=document.getElementById('error');e.hidden=false;e.textContent='화면을 불러오지 못했어요. 다시 열어 주세요.';});</script>
4
+ <script src="appsInTossApp.js"></script></body></html>
@@ -0,0 +1,37 @@
1
+ plugins {
2
+ base
3
+ alias(libs.plugins.kotlin.multiplatform) apply false
4
+ alias(libs.plugins.kotlin.compose) apply false
5
+ alias(libs.plugins.kotlin.serialization) apply false
6
+ alias(libs.plugins.compose) apply false
7
+ alias(libs.plugins.android.kotlin.multiplatform.library) apply false
8
+ alias(libs.plugins.android.application) apply false
9
+ }
10
+
11
+ val ktlint = configurations.create("ktlint") {
12
+ attributes {
13
+ attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
14
+ attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.SHADOWED))
15
+ }
16
+ }
17
+ repositories { mavenCentral() }
18
+ dependencies { ktlint(libs.ktlint.cli) }
19
+
20
+ val kotlinSources = fileTree(rootDir) {
21
+ include("**/*.kt", "**/*.kts")
22
+ exclude("**/build/**", "**/node_modules/**", "**/.gradle/**", "**/.kotlin/**", "**/.yarn/**", "**/vendor/**", "packages/create-ait-cmp-app/templates/**")
23
+ }
24
+
25
+ for ((taskName, format) in listOf("ktlintCheck" to false, "ktlintFormat" to true)) {
26
+ tasks.register<JavaExec>(taskName) {
27
+ group = "verification"
28
+ description = if (format) "Format Kotlin sources and Gradle scripts" else "Lint Kotlin sources and Gradle scripts"
29
+ classpath = ktlint
30
+ mainClass.set("com.pinterest.ktlint.Main")
31
+ if (format) args("--format")
32
+ args(kotlinSources.files.sorted().map { it.absolutePath })
33
+ inputs.files(kotlinSources)
34
+ inputs.file(".editorconfig")
35
+ }
36
+ }
37
+ tasks.named("check") { dependsOn("ktlintCheck") }
@@ -0,0 +1,56 @@
1
+ # 개발 가이드
2
+
3
+ ## 환경 준비
4
+
5
+ Node 24 이상·Corepack·JDK 17이 필요합니다. `packageManager`에 지정한 Yarn 4를 사용합니다. 프로젝트 루트에서 실행합니다.
6
+
7
+ ```sh
8
+ corepack enable
9
+ yarn install --immutable
10
+ ```
11
+
12
+ Android에는 Android SDK 37이, iOS에는 macOS와 Xcode가 추가로 필요합니다. 앱인토스 전용 프로젝트에는 네이티브 개발 도구가 필요하지 않습니다.
13
+
14
+ ## 앱인토스 실행과 배포물 생성
15
+
16
+ ```sh
17
+ yarn dev
18
+ yarn dev:toss
19
+ yarn build
20
+ ```
21
+
22
+ `dev`는 명시적인 mock, `dev:toss`는 실제 브리지를 로컬 네트워크에 제공합니다. 자동 갱신은 없어 소스를 바꾸면 서버를 다시 시작해야 합니다. mock 인가 코드는 서버 인증에 사용하지 않습니다.
23
+
24
+ `build`는 실제 브리지를 포함한 `__APP_NAME__.ait`를 만듭니다. 업로드 전에 `apps-in-toss.config.ts`의 appName·브랜드·권한 등 필수 정보를 콘솔과 맞춥니다. 콘솔 등록·업로드는 자동으로 수행하지 않습니다.
25
+
26
+ 생성 앱의 직접 npm 런타임 의존성은 `@apps-in-toss/web-framework` 하나입니다. JS 브리지는 Kotlin SDK와 같은 버전의 Maven 리소스에 포함되며 웹 빌드가 자동으로 추출합니다. 별도 npm 브리지 설치는 필요하지 않습니다. 정식 CLI 배포물은 같은 버전의 SDK를 Maven Central에서 가져오고, 로컬 개발용 CLI는 `vendor/maven`에 SDK를 포함합니다. TDS는 기본 포함하지 않으며, 사용하려면 앱인토스 호스트에 React/DOM 화면과 관련 의존성을 연결해야 합니다.
27
+
28
+ ## 선택한 플랫폼 실행
29
+
30
+ 선택한 타깃의 디렉터리가 있을 때만 다음 명령을 사용합니다.
31
+
32
+ ```sh
33
+ yarn dev:web
34
+ yarn build:web
35
+ ./gradlew :androidApp:assembleDebug
36
+ ```
37
+
38
+ iOS는 Xcode에서 `iosApp/ServiceSample.xcodeproj`를 열고 서명 팀을 설정합니다. 독립 웹에는 토스 브리지·mock을 포함하지 않습니다. 초안은 기기·브라우저 출처별로 저장하며 계정별 분리·동기화·암호화는 포함하지 않습니다.
39
+
40
+ ## 검사와 GitHub Actions
41
+
42
+ ```sh
43
+ yarn lint
44
+ yarn lint:fix
45
+ ./gradlew :shared-core:jvmTest
46
+ ```
47
+
48
+ Kotlin 검사에는 JDK 17이 필요합니다. 기본 CI는 `.github/workflows/ci.yml`에 포함됩니다. GitHub 저장소에 커밋하고 main에 푸시하면 실행되며, main 대상 PR에서도 실행됩니다. 별도의 secret 설정은 필요하지 않습니다.
49
+
50
+ JS·TS 린트, Kotlin·Gradle 린트, 공통 core JVM 테스트를 실행합니다. 서비스별 JS 테스트·Android·iOS 빌드·기기 실행 검사는 기본 CI에 포함하지 않으며 필요한 시점에 추가합니다.
51
+
52
+ ## 플랫폼 확장
53
+
54
+ 공통 화면과 API 계약은 `shared-ui`·`shared-core`에 유지하고 토스 전용 기능은 `appsInTossApp`에 둡니다. 나중에 플랫폼을 추가하려면 같은 CLI 버전의 템플릿에서 해당 호스트 디렉터리를 가져와 식별자를 바꾸고 Gradle 모듈을 등록합니다. 공통 모듈은 호스트 디렉터리에 따라 Android KMP 플러그인과 iOS 타깃을 활성화합니다.
55
+
56
+ CLI는 기존 프로젝트를 덮어쓰거나 호스트 추가를 자동으로 처리하지 않습니다. 호스트를 추가한 뒤 해당 플랫폼에서 빌드·실행을 확인해야 합니다.
@@ -0,0 +1,19 @@
1
+ import js from '@eslint/js';
2
+ import globals from 'globals';
3
+ import tseslint from 'typescript-eslint';
4
+
5
+ export default [
6
+ { ignores: ['**/build/**', '**/dist/**', '**/node_modules/**', '**/.gradle/**', '**/.kotlin/**', '**/.yarn/**', '**/vendor/**', 'packages/create-ait-cmp-app/templates/**'] },
7
+ js.configs.recommended,
8
+ ...tseslint.configs.recommended,
9
+ {
10
+ files: ['**/*.{js,mjs,ts}'],
11
+ languageOptions: { globals: { ...globals.node, ...globals.browser } },
12
+ rules: {
13
+ 'no-unused-vars': 'off',
14
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', caughtErrors: 'none' }],
15
+ 'no-empty': ['error', { allowEmptyCatch: true }],
16
+ 'eqeqeq': ['error', 'always', { null: 'ignore' }],
17
+ },
18
+ },
19
+ ];
@@ -0,0 +1,31 @@
1
+ [versions]
2
+ kotlin = "2.4.21"
3
+ compose = "1.12.1"
4
+ agp = "9.4.1"
5
+ coroutines = "1.11.0"
6
+ serialization = "1.11.0"
7
+ android-compileSdk = "37"
8
+ android-targetSdk = "37"
9
+ activity = "1.13.0"
10
+ material3 = "1.9.0"
11
+ ktlint = "1.8.0"
12
+ maven-publish = "0.37.0"
13
+ [libraries]
14
+ ktlint-cli = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" }
15
+ coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
16
+ coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
17
+ serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
18
+ androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity" }
19
+ compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "compose" }
20
+ compose-foundation = { module = "org.jetbrains.compose.foundation:foundation", version.ref = "compose" }
21
+ compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "compose" }
22
+ compose-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "compose" }
23
+ compose-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "material3" }
24
+ [plugins]
25
+ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
26
+ kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
27
+ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
28
+ compose = { id = "org.jetbrains.compose", version.ref = "compose" }
29
+ android-kotlin-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
30
+ android-application = { id = "com.android.application", version.ref = "agp" }
31
+ maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
@@ -0,0 +1,10 @@
1
+ distributionBase=GRADLE_USER_HOME
2
+ distributionPath=wrapper/dists
3
+ distributionSha256Sum=dce76f55f8e251a3a1f130eb120f30b3d271de2b76c9b0729d316b5a1b6dc01f
4
+ distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip
5
+ networkTimeout=10000
6
+ retries=0
7
+ retryBackOffMs=500
8
+ validateDistributionUrl=true
9
+ zipStoreBase=GRADLE_USER_HOME
10
+ zipStorePath=wrapper/dists
@@ -0,0 +1,3 @@
1
+ org.gradle.jvmargs=-Xmx4g -Dfile.encoding=UTF-8
2
+ kotlin.code.style=official
3
+ android.useAndroidX=true