@su-record/vibe 2.4.72 → 2.4.76
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.
- package/CLAUDE.md +216 -215
- package/README.md +4 -4
- package/agents/research/best-practices-agent.md +13 -13
- package/agents/research/codebase-patterns-agent.md +33 -33
- package/agents/research/framework-docs-agent.md +23 -23
- package/agents/research/security-advisory-agent.md +29 -29
- package/agents/review/architecture-reviewer.md +31 -31
- package/agents/review/complexity-reviewer.md +21 -21
- package/agents/review/data-integrity-reviewer.md +29 -29
- package/agents/review/git-history-reviewer.md +24 -24
- package/agents/review/performance-reviewer.md +29 -29
- package/agents/review/python-reviewer.md +53 -53
- package/agents/review/rails-reviewer.md +40 -40
- package/agents/review/react-reviewer.md +40 -40
- package/agents/review/security-reviewer.md +29 -29
- package/agents/review/simplicity-reviewer.md +24 -24
- package/agents/review/test-coverage-reviewer.md +31 -31
- package/agents/review/typescript-reviewer.md +41 -41
- package/commands/vibe.analyze.md +103 -7
- package/commands/vibe.reason.md +106 -0
- package/commands/vibe.review.md +123 -38
- package/commands/vibe.run.md +286 -223
- package/commands/vibe.spec.md +425 -186
- package/commands/vibe.utils.md +104 -3
- package/commands/vibe.verify.md +179 -86
- package/dist/cli/detect.js +40 -40
- package/dist/cli/detect.js.map +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/llm.js +5 -5
- package/dist/cli/llm.js.map +1 -1
- package/dist/cli/setup.js +3 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/lib/ContextCompressor.js +1 -1
- package/dist/lib/ContextCompressor.js.map +1 -1
- package/dist/lib/MemoryManager.d.ts +13 -155
- package/dist/lib/MemoryManager.d.ts.map +1 -1
- package/dist/lib/MemoryManager.js +52 -617
- package/dist/lib/MemoryManager.js.map +1 -1
- package/dist/lib/gemini-api.js +12 -12
- package/dist/lib/gemini-api.js.map +1 -1
- package/dist/lib/gemini-oauth.js +22 -22
- package/dist/lib/gemini-oauth.js.map +1 -1
- package/dist/lib/gemini-storage.js +3 -3
- package/dist/lib/gemini-storage.js.map +1 -1
- package/dist/lib/gpt-api.js +11 -11
- package/dist/lib/gpt-api.js.map +1 -1
- package/dist/lib/gpt-oauth.js +28 -28
- package/dist/lib/gpt-oauth.js.map +1 -1
- package/dist/lib/gpt-storage.js +3 -3
- package/dist/lib/gpt-storage.js.map +1 -1
- package/dist/lib/memory/KnowledgeGraph.d.ts +34 -0
- package/dist/lib/memory/KnowledgeGraph.d.ts.map +1 -0
- package/dist/lib/memory/KnowledgeGraph.js +216 -0
- package/dist/lib/memory/KnowledgeGraph.js.map +1 -0
- package/dist/lib/memory/KnowledgeGraph.test.d.ts +2 -0
- package/dist/lib/memory/KnowledgeGraph.test.d.ts.map +1 -0
- package/dist/lib/memory/KnowledgeGraph.test.js +189 -0
- package/dist/lib/memory/KnowledgeGraph.test.js.map +1 -0
- package/dist/lib/memory/MemorySearch.d.ts +25 -0
- package/dist/lib/memory/MemorySearch.d.ts.map +1 -0
- package/dist/lib/memory/MemorySearch.js +85 -0
- package/dist/lib/memory/MemorySearch.js.map +1 -0
- package/dist/lib/memory/MemorySearch.test.d.ts +2 -0
- package/dist/lib/memory/MemorySearch.test.d.ts.map +1 -0
- package/dist/lib/memory/MemorySearch.test.js +149 -0
- package/dist/lib/memory/MemorySearch.test.js.map +1 -0
- package/dist/lib/memory/MemoryStorage.d.ts +77 -0
- package/dist/lib/memory/MemoryStorage.d.ts.map +1 -0
- package/dist/lib/memory/MemoryStorage.js +278 -0
- package/dist/lib/memory/MemoryStorage.js.map +1 -0
- package/dist/lib/memory/MemoryStorage.test.d.ts +2 -0
- package/dist/lib/memory/MemoryStorage.test.d.ts.map +1 -0
- package/dist/lib/memory/MemoryStorage.test.js +198 -0
- package/dist/lib/memory/MemoryStorage.test.js.map +1 -0
- package/dist/lib/memory/index.d.ts +4 -0
- package/dist/lib/memory/index.d.ts.map +1 -0
- package/dist/lib/memory/index.js +8 -0
- package/dist/lib/memory/index.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator/orchestrator.js +4 -6
- package/dist/orchestrator/orchestrator.js.map +1 -1
- package/dist/tools/convention/analyzeComplexity.d.ts +3 -1
- package/dist/tools/convention/analyzeComplexity.d.ts.map +1 -1
- package/dist/tools/convention/analyzeComplexity.js +102 -4
- package/dist/tools/convention/analyzeComplexity.js.map +1 -1
- package/dist/tools/convention/analyzeComplexity.test.d.ts +2 -0
- package/dist/tools/convention/analyzeComplexity.test.d.ts.map +1 -0
- package/dist/tools/convention/analyzeComplexity.test.js +207 -0
- package/dist/tools/convention/analyzeComplexity.test.js.map +1 -0
- package/dist/tools/convention/applyQualityRules.js +1 -1
- package/dist/tools/convention/applyQualityRules.js.map +1 -1
- package/dist/tools/convention/checkCouplingCohesion.js +2 -2
- package/dist/tools/convention/checkCouplingCohesion.js.map +1 -1
- package/dist/tools/convention/suggestImprovements.js +1 -1
- package/dist/tools/convention/suggestImprovements.js.map +1 -1
- package/dist/tools/convention/validateCodeQuality.d.ts +3 -1
- package/dist/tools/convention/validateCodeQuality.d.ts.map +1 -1
- package/dist/tools/convention/validateCodeQuality.js +145 -2
- package/dist/tools/convention/validateCodeQuality.js.map +1 -1
- package/dist/tools/convention/validateCodeQuality.test.d.ts +2 -0
- package/dist/tools/convention/validateCodeQuality.test.d.ts.map +1 -0
- package/dist/tools/convention/validateCodeQuality.test.js +230 -0
- package/dist/tools/convention/validateCodeQuality.test.js.map +1 -0
- package/dist/tools/memory/autoSaveContext.js +1 -1
- package/dist/tools/memory/autoSaveContext.js.map +1 -1
- package/dist/tools/memory/createMemoryTimeline.js +27 -27
- package/dist/tools/memory/createMemoryTimeline.js.map +1 -1
- package/dist/tools/memory/deleteMemory.js +1 -1
- package/dist/tools/memory/deleteMemory.js.map +1 -1
- package/dist/tools/memory/getMemoryGraph.js +24 -24
- package/dist/tools/memory/getMemoryGraph.js.map +1 -1
- package/dist/tools/memory/getSessionContext.js +36 -36
- package/dist/tools/memory/getSessionContext.js.map +1 -1
- package/dist/tools/memory/linkMemories.js +21 -21
- package/dist/tools/memory/linkMemories.js.map +1 -1
- package/dist/tools/memory/prioritizeMemory.js +1 -1
- package/dist/tools/memory/prioritizeMemory.js.map +1 -1
- package/dist/tools/memory/restoreSessionContext.js +1 -1
- package/dist/tools/memory/restoreSessionContext.js.map +1 -1
- package/dist/tools/memory/searchMemories.js +1 -1
- package/dist/tools/memory/searchMemories.js.map +1 -1
- package/dist/tools/memory/searchMemoriesAdvanced.js +42 -42
- package/dist/tools/memory/searchMemoriesAdvanced.js.map +1 -1
- package/dist/tools/memory/startSession.js +2 -2
- package/dist/tools/memory/startSession.js.map +1 -1
- package/dist/tools/memory/updateMemory.js +1 -1
- package/dist/tools/memory/updateMemory.js.map +1 -1
- package/dist/tools/semantic/analyzeDependencyGraph.js +38 -38
- package/dist/tools/semantic/analyzeDependencyGraph.js.map +1 -1
- package/dist/tools/semantic/findReferences.js +1 -1
- package/dist/tools/semantic/findReferences.js.map +1 -1
- package/dist/tools/semantic/findSymbol.js +1 -1
- package/dist/tools/semantic/findSymbol.js.map +1 -1
- package/dist/tools/time/getCurrentTime.js +1 -1
- package/dist/tools/time/getCurrentTime.js.map +1 -1
- package/dist/tools/ui/previewUiAscii.js +2 -2
- package/dist/tools/ui/previewUiAscii.js.map +1 -1
- package/hooks/hooks.json +11 -2
- package/hooks/scripts/llm-orchestrate.js +1 -1
- package/hooks/scripts/utils.js +31 -6
- package/languages/csharp-unity.md +82 -83
- package/languages/dart-flutter.md +89 -88
- package/languages/go.md +76 -75
- package/languages/java-spring.md +85 -84
- package/languages/kotlin-android.md +64 -63
- package/languages/python-django.md +83 -82
- package/languages/python-fastapi.md +82 -81
- package/languages/rust.md +75 -74
- package/languages/swift-ios.md +73 -72
- package/languages/typescript-electron.md +70 -71
- package/languages/typescript-nextjs.md +93 -92
- package/languages/typescript-node.md +64 -63
- package/languages/typescript-nuxt.md +113 -112
- package/languages/typescript-react-native.md +82 -81
- package/languages/typescript-react.md +76 -75
- package/languages/typescript-tauri.md +74 -75
- package/languages/typescript-vue.md +73 -72
- package/package.json +1 -1
- package/skills/git-worktree.md +25 -25
- package/skills/multi-llm-orchestration.md +4 -6
- package/skills/priority-todos.md +39 -39
- package/skills/vibe-capabilities.md +2 -2
- package/vibe/config.json +2 -2
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Kotlin + Android Quality Rules
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Core Principles (inherited from core)
|
|
4
4
|
|
|
5
5
|
```markdown
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
# Core Principles (inherited from core)
|
|
7
|
+
Single Responsibility (SRP)
|
|
8
|
+
No Duplication (DRY)
|
|
9
|
+
Reusability
|
|
10
|
+
Low Complexity
|
|
11
|
+
Function <= 30 lines
|
|
12
|
+
Nesting <= 3 levels
|
|
13
|
+
Cyclomatic complexity <= 10
|
|
13
14
|
```
|
|
14
15
|
|
|
15
|
-
## Kotlin/Android
|
|
16
|
+
## Kotlin/Android Specific Rules
|
|
16
17
|
|
|
17
18
|
### 1. Jetpack Compose UI
|
|
18
19
|
|
|
19
20
|
```kotlin
|
|
20
|
-
//
|
|
21
|
+
// Good: Composable function
|
|
21
22
|
@Composable
|
|
22
23
|
fun UserProfileScreen(
|
|
23
24
|
viewModel: UserProfileViewModel = hiltViewModel(),
|
|
@@ -32,7 +33,7 @@ fun UserProfileScreen(
|
|
|
32
33
|
)
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
//
|
|
36
|
+
// Good: Stateless Composable (reusable)
|
|
36
37
|
@Composable
|
|
37
38
|
private fun UserProfileContent(
|
|
38
39
|
uiState: UserProfileUiState,
|
|
@@ -43,10 +44,10 @@ private fun UserProfileContent(
|
|
|
43
44
|
Scaffold(
|
|
44
45
|
topBar = {
|
|
45
46
|
TopAppBar(
|
|
46
|
-
title = { Text("
|
|
47
|
+
title = { Text("Profile") },
|
|
47
48
|
navigationIcon = {
|
|
48
49
|
IconButton(onClick = onNavigateBack) {
|
|
49
|
-
Icon(Icons.Default.ArrowBack, contentDescription = "
|
|
50
|
+
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
)
|
|
@@ -67,7 +68,7 @@ private fun UserProfileContent(
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
//
|
|
71
|
+
// Good: Reusable component
|
|
71
72
|
@Composable
|
|
72
73
|
fun UserCard(
|
|
73
74
|
user: User,
|
|
@@ -86,7 +87,7 @@ fun UserCard(
|
|
|
86
87
|
) {
|
|
87
88
|
AsyncImage(
|
|
88
89
|
model = user.profileImage,
|
|
89
|
-
contentDescription = "${user.name}
|
|
90
|
+
contentDescription = "${user.name} profile",
|
|
90
91
|
modifier = Modifier
|
|
91
92
|
.size(48.dp)
|
|
92
93
|
.clip(CircleShape)
|
|
@@ -111,7 +112,7 @@ fun UserCard(
|
|
|
111
112
|
### 2. ViewModel (MVVM)
|
|
112
113
|
|
|
113
114
|
```kotlin
|
|
114
|
-
//
|
|
115
|
+
// Good: UiState definition (Sealed Interface)
|
|
115
116
|
sealed interface UserListUiState {
|
|
116
117
|
data object Loading : UserListUiState
|
|
117
118
|
data class Success(
|
|
@@ -121,7 +122,7 @@ sealed interface UserListUiState {
|
|
|
121
122
|
data class Error(val message: String) : UserListUiState
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
//
|
|
125
|
+
// Good: ViewModel with Hilt
|
|
125
126
|
@HiltViewModel
|
|
126
127
|
class UserListViewModel @Inject constructor(
|
|
127
128
|
private val getUsersUseCase: GetUsersUseCase,
|
|
@@ -160,7 +161,7 @@ class UserListViewModel @Inject constructor(
|
|
|
160
161
|
}
|
|
161
162
|
.onFailure { error ->
|
|
162
163
|
_uiState.value = UserListUiState.Error(
|
|
163
|
-
error.message ?: "
|
|
164
|
+
error.message ?: "Failed to load user list"
|
|
164
165
|
)
|
|
165
166
|
}
|
|
166
167
|
}
|
|
@@ -181,7 +182,7 @@ class UserListViewModel @Inject constructor(
|
|
|
181
182
|
.onSuccess { users ->
|
|
182
183
|
_uiState.value = UserListUiState.Success(users, isRefreshing = false)
|
|
183
184
|
}
|
|
184
|
-
.onFailure { /*
|
|
185
|
+
.onFailure { /* Error handling */ }
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
188
|
}
|
|
@@ -190,7 +191,7 @@ class UserListViewModel @Inject constructor(
|
|
|
190
191
|
### 3. UseCase (Clean Architecture)
|
|
191
192
|
|
|
192
193
|
```kotlin
|
|
193
|
-
//
|
|
194
|
+
// Good: UseCase definition
|
|
194
195
|
class GetUsersUseCase @Inject constructor(
|
|
195
196
|
private val userRepository: UserRepository,
|
|
196
197
|
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
|
|
@@ -215,7 +216,7 @@ class CreateUserUseCase @Inject constructor(
|
|
|
215
216
|
private val validator: UserValidator
|
|
216
217
|
) {
|
|
217
218
|
suspend operator fun invoke(request: CreateUserRequest): Result<User> {
|
|
218
|
-
//
|
|
219
|
+
// Validation
|
|
219
220
|
validator.validate(request).onFailure { return Result.failure(it) }
|
|
220
221
|
|
|
221
222
|
return runCatching {
|
|
@@ -225,10 +226,10 @@ class CreateUserUseCase @Inject constructor(
|
|
|
225
226
|
}
|
|
226
227
|
```
|
|
227
228
|
|
|
228
|
-
### 4. Repository
|
|
229
|
+
### 4. Repository Pattern
|
|
229
230
|
|
|
230
231
|
```kotlin
|
|
231
|
-
//
|
|
232
|
+
// Good: Repository Interface
|
|
232
233
|
interface UserRepository {
|
|
233
234
|
suspend fun getUsers(): List<User>
|
|
234
235
|
suspend fun getUser(id: String): User
|
|
@@ -237,7 +238,7 @@ interface UserRepository {
|
|
|
237
238
|
suspend fun deleteUser(id: String)
|
|
238
239
|
}
|
|
239
240
|
|
|
240
|
-
//
|
|
241
|
+
// Good: Repository implementation
|
|
241
242
|
class UserRepositoryImpl @Inject constructor(
|
|
242
243
|
private val apiService: UserApiService,
|
|
243
244
|
private val userDao: UserDao,
|
|
@@ -246,16 +247,16 @@ class UserRepositoryImpl @Inject constructor(
|
|
|
246
247
|
|
|
247
248
|
override suspend fun getUsers(): List<User> = withContext(dispatcher) {
|
|
248
249
|
try {
|
|
249
|
-
//
|
|
250
|
+
// Fetch data from API
|
|
250
251
|
val response = apiService.getUsers()
|
|
251
252
|
val users = response.map { it.toDomain() }
|
|
252
253
|
|
|
253
|
-
//
|
|
254
|
+
// Update local cache
|
|
254
255
|
userDao.insertAll(users.map { it.toEntity() })
|
|
255
256
|
|
|
256
257
|
users
|
|
257
258
|
} catch (e: Exception) {
|
|
258
|
-
//
|
|
259
|
+
// Offline: Return local data
|
|
259
260
|
userDao.getAll().map { it.toDomain() }
|
|
260
261
|
}
|
|
261
262
|
}
|
|
@@ -267,22 +268,22 @@ class UserRepositoryImpl @Inject constructor(
|
|
|
267
268
|
}
|
|
268
269
|
```
|
|
269
270
|
|
|
270
|
-
### 5.
|
|
271
|
+
### 5. Error Handling
|
|
271
272
|
|
|
272
273
|
```kotlin
|
|
273
|
-
//
|
|
274
|
+
// Good: Custom exception
|
|
274
275
|
sealed class AppException(message: String) : Exception(message) {
|
|
275
|
-
class NetworkException(message: String = "
|
|
276
|
-
class UnauthorizedException(message: String = "
|
|
276
|
+
class NetworkException(message: String = "Please check your network connection") : AppException(message)
|
|
277
|
+
class UnauthorizedException(message: String = "Login required") : AppException(message)
|
|
277
278
|
class NotFoundException(
|
|
278
279
|
val resource: String,
|
|
279
280
|
val id: String
|
|
280
|
-
) : AppException("$
|
|
281
|
+
) : AppException("$resource not found (ID: $id)")
|
|
281
282
|
class ServerException(message: String) : AppException(message)
|
|
282
283
|
class ValidationException(message: String) : AppException(message)
|
|
283
284
|
}
|
|
284
285
|
|
|
285
|
-
//
|
|
286
|
+
// Good: Result extension functions
|
|
286
287
|
inline fun <T> Result<T>.onSuccess(action: (T) -> Unit): Result<T> {
|
|
287
288
|
getOrNull()?.let(action)
|
|
288
289
|
return this
|
|
@@ -293,7 +294,7 @@ inline fun <T> Result<T>.onFailure(action: (Throwable) -> Unit): Result<T> {
|
|
|
293
294
|
return this
|
|
294
295
|
}
|
|
295
296
|
|
|
296
|
-
//
|
|
297
|
+
// Good: API response handling
|
|
297
298
|
suspend fun <T> safeApiCall(
|
|
298
299
|
dispatcher: CoroutineDispatcher = Dispatchers.IO,
|
|
299
300
|
apiCall: suspend () -> T
|
|
@@ -305,8 +306,8 @@ suspend fun <T> safeApiCall(
|
|
|
305
306
|
is HttpException -> {
|
|
306
307
|
when (throwable.code()) {
|
|
307
308
|
401 -> throw AppException.UnauthorizedException()
|
|
308
|
-
404 -> throw AppException.NotFoundException("
|
|
309
|
-
else -> throw AppException.ServerException("
|
|
309
|
+
404 -> throw AppException.NotFoundException("Resource", "unknown")
|
|
310
|
+
else -> throw AppException.ServerException("Server error: ${throwable.code()}")
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
313
|
is IOException -> throw AppException.NetworkException()
|
|
@@ -316,10 +317,10 @@ suspend fun <T> safeApiCall(
|
|
|
316
317
|
}
|
|
317
318
|
```
|
|
318
319
|
|
|
319
|
-
### 6. Hilt
|
|
320
|
+
### 6. Hilt Dependency Injection
|
|
320
321
|
|
|
321
322
|
```kotlin
|
|
322
|
-
//
|
|
323
|
+
// Good: Module definition
|
|
323
324
|
@Module
|
|
324
325
|
@InstallIn(SingletonComponent::class)
|
|
325
326
|
object NetworkModule {
|
|
@@ -364,10 +365,10 @@ abstract class RepositoryModule {
|
|
|
364
365
|
}
|
|
365
366
|
```
|
|
366
367
|
|
|
367
|
-
### 7.
|
|
368
|
+
### 7. Testing
|
|
368
369
|
|
|
369
370
|
```kotlin
|
|
370
|
-
//
|
|
371
|
+
// Good: ViewModel test
|
|
371
372
|
@OptIn(ExperimentalCoroutinesApi::class)
|
|
372
373
|
class UserListViewModelTest {
|
|
373
374
|
|
|
@@ -386,11 +387,11 @@ class UserListViewModelTest {
|
|
|
386
387
|
}
|
|
387
388
|
|
|
388
389
|
@Test
|
|
389
|
-
fun `loadUsers
|
|
390
|
+
fun `loadUsers success results in Success state`() = runTest {
|
|
390
391
|
// Given
|
|
391
392
|
val expectedUsers = listOf(
|
|
392
|
-
User(id = "1", name = "
|
|
393
|
-
User(id = "2", name = "
|
|
393
|
+
User(id = "1", name = "Test1", email = "test1@example.com"),
|
|
394
|
+
User(id = "2", name = "Test2", email = "test2@example.com")
|
|
394
395
|
)
|
|
395
396
|
fakeUserRepository.setUsers(expectedUsers)
|
|
396
397
|
|
|
@@ -404,7 +405,7 @@ class UserListViewModelTest {
|
|
|
404
405
|
}
|
|
405
406
|
|
|
406
407
|
@Test
|
|
407
|
-
fun `loadUsers
|
|
408
|
+
fun `loadUsers failure results in Error state`() = runTest {
|
|
408
409
|
// Given
|
|
409
410
|
fakeUserRepository.setShouldReturnError(true)
|
|
410
411
|
|
|
@@ -417,7 +418,7 @@ class UserListViewModelTest {
|
|
|
417
418
|
}
|
|
418
419
|
}
|
|
419
420
|
|
|
420
|
-
//
|
|
421
|
+
// Good: Fake Repository
|
|
421
422
|
class FakeUserRepository : UserRepository {
|
|
422
423
|
private var users = mutableListOf<User>()
|
|
423
424
|
private var shouldReturnError = false
|
|
@@ -435,37 +436,37 @@ class FakeUserRepository : UserRepository {
|
|
|
435
436
|
return users
|
|
436
437
|
}
|
|
437
438
|
|
|
438
|
-
// ...
|
|
439
|
+
// ... other methods
|
|
439
440
|
}
|
|
440
441
|
```
|
|
441
442
|
|
|
442
|
-
##
|
|
443
|
+
## File Structure
|
|
443
444
|
|
|
444
445
|
```
|
|
445
446
|
app/
|
|
446
447
|
├── src/main/java/com/example/app/
|
|
447
|
-
│ ├── di/ # Hilt
|
|
448
|
+
│ ├── di/ # Hilt modules
|
|
448
449
|
│ │ ├── NetworkModule.kt
|
|
449
450
|
│ │ └── RepositoryModule.kt
|
|
450
451
|
│ ├── data/
|
|
451
|
-
│ │ ├── api/ # API
|
|
452
|
+
│ │ ├── api/ # API services
|
|
452
453
|
│ │ │ └── UserApiService.kt
|
|
453
454
|
│ │ ├── local/ # Room DAO
|
|
454
455
|
│ │ │ └── UserDao.kt
|
|
455
456
|
│ │ ├── model/ # DTO
|
|
456
457
|
│ │ │ └── UserDto.kt
|
|
457
|
-
│ │ └── repository/ # Repository
|
|
458
|
+
│ │ └── repository/ # Repository implementation
|
|
458
459
|
│ │ └── UserRepositoryImpl.kt
|
|
459
460
|
│ ├── domain/
|
|
460
|
-
│ │ ├── model/ #
|
|
461
|
+
│ │ ├── model/ # Domain models
|
|
461
462
|
│ │ │ └── User.kt
|
|
462
|
-
│ │ ├── repository/ # Repository
|
|
463
|
+
│ │ ├── repository/ # Repository interfaces
|
|
463
464
|
│ │ │ └── UserRepository.kt
|
|
464
465
|
│ │ └── usecase/ # UseCase
|
|
465
466
|
│ │ └── GetUsersUseCase.kt
|
|
466
467
|
│ └── presentation/
|
|
467
468
|
│ ├── ui/
|
|
468
|
-
│ │ ├── components/ #
|
|
469
|
+
│ │ ├── components/ # Common Composables
|
|
469
470
|
│ │ └── theme/ # Material Theme
|
|
470
471
|
│ └── feature/
|
|
471
472
|
│ └── user/
|
|
@@ -479,13 +480,13 @@ app/
|
|
|
479
480
|
└── UserListViewModelTest.kt
|
|
480
481
|
```
|
|
481
482
|
|
|
482
|
-
##
|
|
483
|
+
## Checklist
|
|
483
484
|
|
|
484
|
-
- [ ] Jetpack Compose
|
|
485
|
-
- [ ]
|
|
486
|
-
- [ ] Sealed Interface
|
|
487
|
-
- [ ] Hilt
|
|
488
|
-
- [ ]
|
|
489
|
-
- [ ]
|
|
490
|
-
- [ ] Result/runCatching
|
|
491
|
-
- [ ] collectAsStateWithLifecycle()
|
|
485
|
+
- [ ] Use Jetpack Compose (avoid XML layouts)
|
|
486
|
+
- [ ] Manage UI state with StateFlow
|
|
487
|
+
- [ ] Define UiState with Sealed Interface
|
|
488
|
+
- [ ] Use Hilt for dependency injection
|
|
489
|
+
- [ ] Separate business logic with UseCase
|
|
490
|
+
- [ ] Abstract data layer with Repository pattern
|
|
491
|
+
- [ ] Handle errors with Result/runCatching
|
|
492
|
+
- [ ] Use collectAsStateWithLifecycle()
|