@c0x12c/ai-toolkit 1.15.0
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-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +12 -0
- package/README.md +439 -0
- package/VERSION +1 -0
- package/agents/design-critic.md +127 -0
- package/agents/idea-killer.md +72 -0
- package/agents/infrastructure-expert.md +49 -0
- package/agents/micronaut-backend-expert.md +45 -0
- package/agents/phase-reviewer.md +150 -0
- package/agents/research-planner.md +70 -0
- package/agents/solution-architect-cto.md +49 -0
- package/agents/sre-architect.md +49 -0
- package/agents/team-coordinator.md +111 -0
- package/bin/cli.js +780 -0
- package/claude-md/00-header.md +39 -0
- package/claude-md/01-core.md +105 -0
- package/claude-md/05-database.md +20 -0
- package/claude-md/11-backend-micronaut.md +19 -0
- package/claude-md/20-frontend-react.md +44 -0
- package/claude-md/25-ux-design.md +56 -0
- package/claude-md/30-infrastructure.md +24 -0
- package/claude-md/30-project-mgmt.md +119 -0
- package/claude-md/40-product.md +39 -0
- package/claude-md/50-ops.md +34 -0
- package/claude-md/60-research.md +27 -0
- package/claude-md/90-footer.md +21 -0
- package/commands/spartan/brainstorm.md +134 -0
- package/commands/spartan/brownfield.md +157 -0
- package/commands/spartan/build.md +435 -0
- package/commands/spartan/careful.md +94 -0
- package/commands/spartan/commit-message.md +112 -0
- package/commands/spartan/content.md +17 -0
- package/commands/spartan/context-save.md +161 -0
- package/commands/spartan/contribute.md +140 -0
- package/commands/spartan/daily.md +42 -0
- package/commands/spartan/debug.md +308 -0
- package/commands/spartan/deep-dive.md +55 -0
- package/commands/spartan/deploy.md +207 -0
- package/commands/spartan/e2e.md +264 -0
- package/commands/spartan/env-setup.md +166 -0
- package/commands/spartan/epic.md +199 -0
- package/commands/spartan/fe-review.md +181 -0
- package/commands/spartan/figma-to-code.md +260 -0
- package/commands/spartan/forensics.md +46 -0
- package/commands/spartan/freeze.md +84 -0
- package/commands/spartan/fundraise.md +53 -0
- package/commands/spartan/gate-review.md +229 -0
- package/commands/spartan/gsd-upgrade.md +376 -0
- package/commands/spartan/guard.md +42 -0
- package/commands/spartan/init-project.md +178 -0
- package/commands/spartan/init-rules.md +298 -0
- package/commands/spartan/interview.md +154 -0
- package/commands/spartan/kickoff.md +73 -0
- package/commands/spartan/kotlin-service.md +109 -0
- package/commands/spartan/lean-canvas.md +222 -0
- package/commands/spartan/lint-rules.md +122 -0
- package/commands/spartan/map-codebase.md +124 -0
- package/commands/spartan/migration.md +82 -0
- package/commands/spartan/next-app.md +317 -0
- package/commands/spartan/next-feature.md +212 -0
- package/commands/spartan/onboard.md +326 -0
- package/commands/spartan/outreach.md +16 -0
- package/commands/spartan/phase.md +142 -0
- package/commands/spartan/pitch.md +18 -0
- package/commands/spartan/plan.md +210 -0
- package/commands/spartan/pr-ready.md +202 -0
- package/commands/spartan/project.md +106 -0
- package/commands/spartan/qa.md +222 -0
- package/commands/spartan/research.md +254 -0
- package/commands/spartan/review.md +132 -0
- package/commands/spartan/scan-rules.md +173 -0
- package/commands/spartan/sessions.md +143 -0
- package/commands/spartan/spec.md +131 -0
- package/commands/spartan/startup.md +257 -0
- package/commands/spartan/team.md +570 -0
- package/commands/spartan/teardown.md +161 -0
- package/commands/spartan/testcontainer.md +97 -0
- package/commands/spartan/tf-cost.md +123 -0
- package/commands/spartan/tf-deploy.md +116 -0
- package/commands/spartan/tf-drift.md +100 -0
- package/commands/spartan/tf-import.md +107 -0
- package/commands/spartan/tf-module.md +121 -0
- package/commands/spartan/tf-plan.md +100 -0
- package/commands/spartan/tf-review.md +106 -0
- package/commands/spartan/tf-scaffold.md +109 -0
- package/commands/spartan/tf-security.md +147 -0
- package/commands/spartan/think.md +221 -0
- package/commands/spartan/unfreeze.md +13 -0
- package/commands/spartan/update.md +134 -0
- package/commands/spartan/ux.md +1233 -0
- package/commands/spartan/validate.md +193 -0
- package/commands/spartan/web-to-prd.md +706 -0
- package/commands/spartan/workstreams.md +109 -0
- package/commands/spartan/write.md +16 -0
- package/commands/spartan.md +386 -0
- package/frameworks/00-framework-comparison-guide.md +317 -0
- package/frameworks/01-lean-canvas.md +196 -0
- package/frameworks/02-design-sprint.md +304 -0
- package/frameworks/03-foundation-sprint.md +337 -0
- package/frameworks/04-business-model-canvas.md +391 -0
- package/frameworks/05-customer-development.md +426 -0
- package/frameworks/06-jobs-to-be-done.md +358 -0
- package/frameworks/07-mom-test.md +392 -0
- package/frameworks/08-value-proposition-canvas.md +488 -0
- package/frameworks/09-javelin-board.md +428 -0
- package/frameworks/10-build-measure-learn.md +467 -0
- package/frameworks/11-mvp-approaches.md +533 -0
- package/frameworks/think-before-build.md +593 -0
- package/lib/assembler.js +197 -0
- package/lib/assembler.test.js +159 -0
- package/lib/detector.js +166 -0
- package/lib/detector.test.js +221 -0
- package/lib/packs.js +16 -0
- package/lib/resolver.js +272 -0
- package/lib/resolver.test.js +298 -0
- package/lib/worktree.sh +104 -0
- package/package.json +50 -0
- package/packs/backend-micronaut.yaml +35 -0
- package/packs/backend-nodejs.yaml +15 -0
- package/packs/backend-python.yaml +15 -0
- package/packs/core.yaml +37 -0
- package/packs/database.yaml +21 -0
- package/packs/frontend-react.yaml +24 -0
- package/packs/infrastructure.yaml +40 -0
- package/packs/ops.yaml +16 -0
- package/packs/packs.compiled.json +371 -0
- package/packs/product.yaml +22 -0
- package/packs/project-mgmt.yaml +24 -0
- package/packs/research.yaml +39 -0
- package/packs/shared-backend.yaml +14 -0
- package/packs/ux-design.yaml +21 -0
- package/rules/backend-micronaut/API_DESIGN.md +313 -0
- package/rules/backend-micronaut/BATCH_PROCESSING.md +92 -0
- package/rules/backend-micronaut/CONTROLLERS.md +388 -0
- package/rules/backend-micronaut/KOTLIN.md +414 -0
- package/rules/backend-micronaut/RETROFIT_PLACEMENT.md +290 -0
- package/rules/backend-micronaut/SERVICES_AND_BEANS.md +325 -0
- package/rules/core/NAMING_CONVENTIONS.md +208 -0
- package/rules/core/SKILL_AUTHORING.md +174 -0
- package/rules/core/TIMEZONE.md +316 -0
- package/rules/database/ORM_AND_REPO.md +289 -0
- package/rules/database/SCHEMA.md +146 -0
- package/rules/database/TRANSACTIONS.md +311 -0
- package/rules/frontend-react/FRONTEND.md +344 -0
- package/rules/infrastructure/MODULES.md +260 -0
- package/rules/infrastructure/NAMING.md +196 -0
- package/rules/infrastructure/PROVIDERS.md +309 -0
- package/rules/infrastructure/SECURITY.md +310 -0
- package/rules/infrastructure/STATE_AND_BACKEND.md +237 -0
- package/rules/infrastructure/STRUCTURE.md +234 -0
- package/rules/infrastructure/VARIABLES.md +285 -0
- package/rules/shared-backend/ARCHITECTURE.md +46 -0
- package/rules/ux-design/DESIGN_PROCESS.md +176 -0
- package/skills/api-endpoint-creator/SKILL.md +455 -0
- package/skills/api-endpoint-creator/error-handling-guide.md +244 -0
- package/skills/api-endpoint-creator/examples.md +522 -0
- package/skills/api-endpoint-creator/testing-patterns.md +302 -0
- package/skills/article-writing/SKILL.md +109 -0
- package/skills/article-writing/examples.md +59 -0
- package/skills/backend-api-design/SKILL.md +84 -0
- package/skills/backend-api-design/code-patterns.md +138 -0
- package/skills/brainstorm/SKILL.md +95 -0
- package/skills/browser-qa/SKILL.md +87 -0
- package/skills/browser-qa/playwright-snippets.md +110 -0
- package/skills/ci-cd-patterns/SKILL.md +108 -0
- package/skills/ci-cd-patterns/workflows.md +149 -0
- package/skills/competitive-teardown/SKILL.md +93 -0
- package/skills/competitive-teardown/example-analysis.md +50 -0
- package/skills/content-engine/SKILL.md +131 -0
- package/skills/content-engine/examples.md +72 -0
- package/skills/database-patterns/SKILL.md +72 -0
- package/skills/database-patterns/code-templates.md +114 -0
- package/skills/database-table-creator/SKILL.md +141 -0
- package/skills/database-table-creator/examples.md +552 -0
- package/skills/database-table-creator/kotlin-templates.md +400 -0
- package/skills/database-table-creator/migration-template.sql +68 -0
- package/skills/database-table-creator/validation-checklist.md +337 -0
- package/skills/deep-research/SKILL.md +80 -0
- package/skills/design-intelligence/SKILL.md +268 -0
- package/skills/design-workflow/SKILL.md +127 -0
- package/skills/design-workflow/checklists.md +45 -0
- package/skills/idea-validation/SKILL.md +129 -0
- package/skills/idea-validation/example-report.md +50 -0
- package/skills/investor-materials/SKILL.md +122 -0
- package/skills/investor-materials/example-outline.md +70 -0
- package/skills/investor-outreach/SKILL.md +112 -0
- package/skills/investor-outreach/examples.md +76 -0
- package/skills/kotlin-best-practices/SKILL.md +58 -0
- package/skills/kotlin-best-practices/code-patterns.md +132 -0
- package/skills/market-research/SKILL.md +99 -0
- package/skills/security-checklist/SKILL.md +65 -0
- package/skills/security-checklist/audit-reference.md +95 -0
- package/skills/service-debugging/SKILL.md +116 -0
- package/skills/service-debugging/common-issues.md +65 -0
- package/skills/startup-pipeline/SKILL.md +152 -0
- package/skills/terraform-best-practices/SKILL.md +244 -0
- package/skills/terraform-module-creator/SKILL.md +284 -0
- package/skills/terraform-review/SKILL.md +222 -0
- package/skills/terraform-security-audit/SKILL.md +280 -0
- package/skills/terraform-service-scaffold/SKILL.md +574 -0
- package/skills/testing-strategies/SKILL.md +116 -0
- package/skills/testing-strategies/examples.md +103 -0
- package/skills/testing-strategies/integration-test-setup.md +71 -0
- package/skills/ui-ux-pro-max/SKILL.md +238 -0
- package/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/ui-ux-pro-max/python-setup.md +146 -0
- package/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/skills/ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/web-to-prd/SKILL.md +478 -0
- package/templates/build-config.yaml +44 -0
- package/templates/commands-config.yaml +55 -0
- package/templates/competitor-analysis.md +60 -0
- package/templates/content/AGENT_TEMPLATE.md +47 -0
- package/templates/content/COMMAND_TEMPLATE.md +27 -0
- package/templates/content/RULE_TEMPLATE.md +40 -0
- package/templates/content/SKILL_TEMPLATE.md +41 -0
- package/templates/design-config.md +105 -0
- package/templates/design-doc.md +207 -0
- package/templates/epic.md +100 -0
- package/templates/feature-spec.md +181 -0
- package/templates/idea-canvas.md +47 -0
- package/templates/implementation-plan.md +159 -0
- package/templates/prd-template.md +86 -0
- package/templates/preamble.md +89 -0
- package/templates/project-readme.md +35 -0
- package/templates/quality-gates.md +230 -0
- package/templates/spartan-config.yaml +164 -0
- package/templates/user-interview.md +69 -0
- package/templates/validation-checklist.md +108 -0
- package/templates/workflow-backend-micronaut.md +409 -0
- package/templates/workflow-frontend-react.md +233 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Error Handling Guide - Either Type Usage
|
|
2
|
+
|
|
3
|
+
How to use Arrow's `Either` type for error handling in the platform.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Either Basics
|
|
8
|
+
|
|
9
|
+
```kotlin
|
|
10
|
+
sealed class Either<out L, out R>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- **Left** = Error case
|
|
14
|
+
- **Right** = Success case
|
|
15
|
+
|
|
16
|
+
Type signature: `Either<ErrorType, SuccessType>`
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Core Pattern
|
|
21
|
+
|
|
22
|
+
### Manager Returns Either
|
|
23
|
+
|
|
24
|
+
```kotlin
|
|
25
|
+
interface ProjectManager {
|
|
26
|
+
suspend fun byId(id: UUID): Either<ClientException, ProjectResponse>
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Controller Unwraps Either
|
|
31
|
+
|
|
32
|
+
```kotlin
|
|
33
|
+
@Get("/project")
|
|
34
|
+
suspend fun getProject(@QueryValue id: UUID): ProjectResponse {
|
|
35
|
+
return projectManager.byId(id).throwOrValue()
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Creating Either Values
|
|
42
|
+
|
|
43
|
+
### Success (Right)
|
|
44
|
+
|
|
45
|
+
```kotlin
|
|
46
|
+
import arrow.core.right
|
|
47
|
+
|
|
48
|
+
fun getUser(id: UUID): Either<ClientException, UserResponse> {
|
|
49
|
+
val user = repository.byId(id) ?: return error...
|
|
50
|
+
return UserResponse.from(user).right()
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Error (Left)
|
|
55
|
+
|
|
56
|
+
```kotlin
|
|
57
|
+
import arrow.core.left
|
|
58
|
+
|
|
59
|
+
fun getUser(id: UUID): Either<ClientException, UserResponse> {
|
|
60
|
+
val user = repository.byId(id)
|
|
61
|
+
?: return ClientError.USER_NOT_FOUND.asException().left()
|
|
62
|
+
return UserResponse.from(user).right()
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Common Patterns
|
|
69
|
+
|
|
70
|
+
### Pattern 1: Null Check with Error
|
|
71
|
+
|
|
72
|
+
```kotlin
|
|
73
|
+
override suspend fun byId(id: UUID): Either<ClientException, ProjectResponse> {
|
|
74
|
+
val entity = projectRepository.byId(id)
|
|
75
|
+
?: return ClientError.PROJECT_NOT_FOUND.asException().left()
|
|
76
|
+
return ProjectResponse.from(entity, ownerName).right()
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Pattern 2: Multiple Validations
|
|
81
|
+
|
|
82
|
+
```kotlin
|
|
83
|
+
override suspend fun update(
|
|
84
|
+
id: UUID,
|
|
85
|
+
email: String?
|
|
86
|
+
): Either<ClientException, UserResponse> {
|
|
87
|
+
val existing = userRepository.byId(id)
|
|
88
|
+
?: return ClientError.USER_NOT_FOUND.asException().left()
|
|
89
|
+
|
|
90
|
+
if (email != null && email != existing.email) {
|
|
91
|
+
val duplicate = userRepository.byEmail(email)
|
|
92
|
+
if (duplicate != null) {
|
|
93
|
+
return ClientError.EMAIL_ALREADY_IN_USE.asException().left()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
val updated = userRepository.update(id, email)
|
|
98
|
+
?: return ClientError.USER_NOT_FOUND.asException().left()
|
|
99
|
+
|
|
100
|
+
return UserResponse.from(updated).right()
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Pattern 3: Transaction with Multiple Operations
|
|
105
|
+
|
|
106
|
+
```kotlin
|
|
107
|
+
override suspend fun reassignProject(
|
|
108
|
+
projectId: UUID,
|
|
109
|
+
newOwnerId: UUID
|
|
110
|
+
): Either<ClientException, ProjectResponse> {
|
|
111
|
+
val project = projectRepository.byId(projectId)
|
|
112
|
+
?: return ClientError.PROJECT_NOT_FOUND.asException().left()
|
|
113
|
+
|
|
114
|
+
val newOwner = employeeRepository.byId(newOwnerId)
|
|
115
|
+
?: return ClientError.EMPLOYEE_NOT_FOUND.asException().left()
|
|
116
|
+
|
|
117
|
+
val updated = transaction(db.primary) {
|
|
118
|
+
projectRepository.update(projectId, ownerEmployeeId = newOwnerId)
|
|
119
|
+
} ?: return ClientError.PROJECT_NOT_FOUND.asException().left()
|
|
120
|
+
|
|
121
|
+
return ProjectResponse.from(updated, newOwner.name).right()
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## ClientError Enum
|
|
128
|
+
|
|
129
|
+
Error types are in `app/module-exception/`:
|
|
130
|
+
|
|
131
|
+
```kotlin
|
|
132
|
+
enum class ClientError(
|
|
133
|
+
override val status: HttpStatus,
|
|
134
|
+
override val code: Int,
|
|
135
|
+
override val message: String
|
|
136
|
+
) : Error {
|
|
137
|
+
USER_NOT_FOUND(HttpStatus.NOT_FOUND, 3001, "User not found"),
|
|
138
|
+
PROJECT_NOT_FOUND(HttpStatus.NOT_FOUND, 4110, "Project not found"),
|
|
139
|
+
EMPLOYEE_NOT_FOUND(HttpStatus.NOT_FOUND, 4105, "Employee not found"),
|
|
140
|
+
// ...
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Usage:
|
|
145
|
+
```kotlin
|
|
146
|
+
ClientError.USER_NOT_FOUND.asException().left()
|
|
147
|
+
ClientError.USER_NOT_FOUND.asException("Custom message").left()
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### HTTP Status Mapping
|
|
151
|
+
|
|
152
|
+
The exception handler maps errors to HTTP status codes automatically:
|
|
153
|
+
- `*_NOT_FOUND` -> 404 Not Found
|
|
154
|
+
- `EMAIL_ALREADY_IN_USE` -> 409 Conflict
|
|
155
|
+
- `INVALID_CREDENTIALS` -> 401 Unauthorized
|
|
156
|
+
- Validation errors -> 400 Bad Request
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Controller Layer
|
|
161
|
+
|
|
162
|
+
### throwOrValue()
|
|
163
|
+
|
|
164
|
+
```kotlin
|
|
165
|
+
@Get("/project")
|
|
166
|
+
suspend fun getProject(@QueryValue id: UUID): ProjectResponse {
|
|
167
|
+
return projectManager.byId(id).throwOrValue()
|
|
168
|
+
// Returns ProjectResponse if Right
|
|
169
|
+
// Throws ClientException if Left
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Common Mistakes
|
|
176
|
+
|
|
177
|
+
**Wrong: Throwing in manager**
|
|
178
|
+
```kotlin
|
|
179
|
+
override suspend fun byId(id: UUID): Either<ClientException, ProjectResponse> {
|
|
180
|
+
val entity = projectRepository.byId(id)
|
|
181
|
+
?: throw NotFoundException("Not found")
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Correct: Return Left**
|
|
186
|
+
```kotlin
|
|
187
|
+
override suspend fun byId(id: UUID): Either<ClientException, ProjectResponse> {
|
|
188
|
+
val entity = projectRepository.byId(id)
|
|
189
|
+
?: return ClientError.PROJECT_NOT_FOUND.asException().left()
|
|
190
|
+
return ProjectResponse.from(entity, ownerName).right()
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
**Wrong: Using !!**
|
|
197
|
+
```kotlin
|
|
198
|
+
val entity = repository.byId(id)!!
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Correct: Safe null handling**
|
|
202
|
+
```kotlin
|
|
203
|
+
val entity = repository.byId(id)
|
|
204
|
+
?: return ClientError.NOT_FOUND.asException().left()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
**Wrong: Returning Either from controller**
|
|
210
|
+
```kotlin
|
|
211
|
+
@Get("/project")
|
|
212
|
+
suspend fun getProject(@QueryValue id: UUID): Either<ClientException, ProjectResponse> {
|
|
213
|
+
return projectManager.byId(id)
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Correct: Unwrap with throwOrValue**
|
|
218
|
+
```kotlin
|
|
219
|
+
@Get("/project")
|
|
220
|
+
suspend fun getProject(@QueryValue id: UUID): ProjectResponse {
|
|
221
|
+
return projectManager.byId(id).throwOrValue()
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Quick Reference
|
|
228
|
+
|
|
229
|
+
| Scenario | Pattern |
|
|
230
|
+
|----------|---------|
|
|
231
|
+
| Success | `return value.right()` |
|
|
232
|
+
| Not Found | `return ClientError.NOT_FOUND.asException().left()` |
|
|
233
|
+
| Already Exists | `return ClientError.ALREADY_EXISTS.asException().left()` |
|
|
234
|
+
| Unauthorized | `return ClientError.UNAUTHORIZED.asException().left()` |
|
|
235
|
+
| Null Check | `val x = repo.get() ?: return ERROR.asException().left()` |
|
|
236
|
+
| Unwrap in Controller | `manager.method().throwOrValue()` |
|
|
237
|
+
|
|
238
|
+
## Rules
|
|
239
|
+
|
|
240
|
+
1. Managers always return Either
|
|
241
|
+
2. Controllers always use throwOrValue
|
|
242
|
+
3. Never throw exceptions in managers
|
|
243
|
+
4. Never use `!!` operator
|
|
244
|
+
5. Use ClientError enum for errors
|