oh-my-customcode 0.12.1 → 0.12.3

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 (134) hide show
  1. package/README.md +8 -11
  2. package/dist/cli/index.js +137 -336
  3. package/dist/index.js +99 -260
  4. package/package.json +2 -4
  5. package/templates/.claude/skills/codex-exec/SKILL.md +123 -0
  6. package/templates/.claude/skills/codex-exec/scripts/codex-wrapper.cjs +413 -0
  7. package/templates/CLAUDE.md.en +1 -0
  8. package/templates/CLAUDE.md.ko +1 -0
  9. package/templates/.codex/agents/arch-documenter.md +0 -33
  10. package/templates/.codex/agents/arch-speckit-agent.md +0 -47
  11. package/templates/.codex/agents/be-express-expert.md +0 -30
  12. package/templates/.codex/agents/be-fastapi-expert.md +0 -43
  13. package/templates/.codex/agents/be-go-backend-expert.md +0 -43
  14. package/templates/.codex/agents/be-nestjs-expert.md +0 -28
  15. package/templates/.codex/agents/be-springboot-expert.md +0 -40
  16. package/templates/.codex/agents/db-postgres-expert.md +0 -36
  17. package/templates/.codex/agents/db-redis-expert.md +0 -36
  18. package/templates/.codex/agents/db-supabase-expert.md +0 -35
  19. package/templates/.codex/agents/de-airflow-expert.md +0 -34
  20. package/templates/.codex/agents/de-dbt-expert.md +0 -34
  21. package/templates/.codex/agents/de-kafka-expert.md +0 -81
  22. package/templates/.codex/agents/de-pipeline-expert.md +0 -32
  23. package/templates/.codex/agents/de-snowflake-expert.md +0 -36
  24. package/templates/.codex/agents/de-spark-expert.md +0 -36
  25. package/templates/.codex/agents/fe-svelte-agent.md +0 -29
  26. package/templates/.codex/agents/fe-vercel-agent.md +0 -37
  27. package/templates/.codex/agents/fe-vuejs-agent.md +0 -30
  28. package/templates/.codex/agents/infra-aws-expert.md +0 -47
  29. package/templates/.codex/agents/infra-docker-expert.md +0 -47
  30. package/templates/.codex/agents/lang-golang-expert.md +0 -43
  31. package/templates/.codex/agents/lang-java21-expert.md +0 -39
  32. package/templates/.codex/agents/lang-kotlin-expert.md +0 -43
  33. package/templates/.codex/agents/lang-python-expert.md +0 -43
  34. package/templates/.codex/agents/lang-rust-expert.md +0 -43
  35. package/templates/.codex/agents/lang-typescript-expert.md +0 -43
  36. package/templates/.codex/agents/mgr-claude-code-bible.md +0 -58
  37. package/templates/.codex/agents/mgr-creator.md +0 -39
  38. package/templates/.codex/agents/mgr-gitnerd.md +0 -45
  39. package/templates/.codex/agents/mgr-sauron.md +0 -161
  40. package/templates/.codex/agents/mgr-supplier.md +0 -35
  41. package/templates/.codex/agents/mgr-sync-checker.md +0 -38
  42. package/templates/.codex/agents/mgr-updater.md +0 -33
  43. package/templates/.codex/agents/qa-engineer.md +0 -32
  44. package/templates/.codex/agents/qa-planner.md +0 -73
  45. package/templates/.codex/agents/qa-writer.md +0 -27
  46. package/templates/.codex/agents/sys-memory-keeper.md +0 -43
  47. package/templates/.codex/agents/sys-naggy.md +0 -37
  48. package/templates/.codex/agents/tool-bun-expert.md +0 -26
  49. package/templates/.codex/agents/tool-npm-expert.md +0 -30
  50. package/templates/.codex/agents/tool-optimizer.md +0 -34
  51. package/templates/.codex/codex-native-hash.txt +0 -1
  52. package/templates/.codex/contexts/dev.md +0 -20
  53. package/templates/.codex/contexts/ecomode.md +0 -63
  54. package/templates/.codex/contexts/index.yaml +0 -41
  55. package/templates/.codex/contexts/research.md +0 -28
  56. package/templates/.codex/contexts/review.md +0 -23
  57. package/templates/.codex/hooks/hooks.json +0 -150
  58. package/templates/.codex/install-hooks.sh +0 -100
  59. package/templates/.codex/rules/MAY-optimization.md +0 -29
  60. package/templates/.codex/rules/MUST-agent-design.md +0 -57
  61. package/templates/.codex/rules/MUST-agent-identification.md +0 -29
  62. package/templates/.codex/rules/MUST-continuous-improvement.md +0 -25
  63. package/templates/.codex/rules/MUST-intent-transparency.md +0 -42
  64. package/templates/.codex/rules/MUST-language-policy.md +0 -27
  65. package/templates/.codex/rules/MUST-orchestrator-coordination.md +0 -128
  66. package/templates/.codex/rules/MUST-parallel-execution.md +0 -97
  67. package/templates/.codex/rules/MUST-permissions.md +0 -30
  68. package/templates/.codex/rules/MUST-safety.md +0 -23
  69. package/templates/.codex/rules/MUST-sync-verification.md +0 -125
  70. package/templates/.codex/rules/MUST-tool-identification.md +0 -82
  71. package/templates/.codex/rules/SHOULD-agent-teams.md +0 -39
  72. package/templates/.codex/rules/SHOULD-ecomode.md +0 -37
  73. package/templates/.codex/rules/SHOULD-error-handling.md +0 -33
  74. package/templates/.codex/rules/SHOULD-hud-statusline.md +0 -32
  75. package/templates/.codex/rules/SHOULD-interaction.md +0 -34
  76. package/templates/.codex/rules/SHOULD-memory-integration.md +0 -39
  77. package/templates/.codex/rules/index.yaml +0 -141
  78. package/templates/.codex/skills/airflow-best-practices/SKILL.md +0 -56
  79. package/templates/.codex/skills/audit-agents/SKILL.md +0 -116
  80. package/templates/.codex/skills/aws-best-practices/SKILL.md +0 -280
  81. package/templates/.codex/skills/claude-code-bible/SKILL.md +0 -100
  82. package/templates/.codex/skills/claude-code-bible/scripts/fetch-docs.js +0 -272
  83. package/templates/.codex/skills/create-agent/SKILL.md +0 -91
  84. package/templates/.codex/skills/dbt-best-practices/SKILL.md +0 -54
  85. package/templates/.codex/skills/de-lead-routing/SKILL.md +0 -243
  86. package/templates/.codex/skills/dev-lead-routing/SKILL.md +0 -94
  87. package/templates/.codex/skills/dev-refactor/SKILL.md +0 -123
  88. package/templates/.codex/skills/dev-review/SKILL.md +0 -81
  89. package/templates/.codex/skills/docker-best-practices/SKILL.md +0 -275
  90. package/templates/.codex/skills/fastapi-best-practices/SKILL.md +0 -270
  91. package/templates/.codex/skills/fix-refs/SKILL.md +0 -107
  92. package/templates/.codex/skills/go-backend-best-practices/SKILL.md +0 -338
  93. package/templates/.codex/skills/go-best-practices/SKILL.md +0 -203
  94. package/templates/.codex/skills/help/SKILL.md +0 -125
  95. package/templates/.codex/skills/intent-detection/SKILL.md +0 -215
  96. package/templates/.codex/skills/intent-detection/patterns/agent-triggers.yaml +0 -349
  97. package/templates/.codex/skills/kafka-best-practices/SKILL.md +0 -52
  98. package/templates/.codex/skills/kotlin-best-practices/SKILL.md +0 -256
  99. package/templates/.codex/skills/lists/SKILL.md +0 -78
  100. package/templates/.codex/skills/memory-management/SKILL.md +0 -195
  101. package/templates/.codex/skills/memory-recall/SKILL.md +0 -152
  102. package/templates/.codex/skills/memory-save/SKILL.md +0 -126
  103. package/templates/.codex/skills/monitoring-setup/SKILL.md +0 -115
  104. package/templates/.codex/skills/npm-audit/SKILL.md +0 -72
  105. package/templates/.codex/skills/npm-publish/SKILL.md +0 -63
  106. package/templates/.codex/skills/npm-version/SKILL.md +0 -75
  107. package/templates/.codex/skills/optimize-analyze/SKILL.md +0 -55
  108. package/templates/.codex/skills/optimize-bundle/SKILL.md +0 -67
  109. package/templates/.codex/skills/optimize-report/SKILL.md +0 -74
  110. package/templates/.codex/skills/pipeline-architecture-patterns/SKILL.md +0 -83
  111. package/templates/.codex/skills/postgres-best-practices/SKILL.md +0 -66
  112. package/templates/.codex/skills/python-best-practices/SKILL.md +0 -222
  113. package/templates/.codex/skills/qa-lead-routing/SKILL.md +0 -290
  114. package/templates/.codex/skills/react-best-practices/SKILL.md +0 -101
  115. package/templates/.codex/skills/redis-best-practices/SKILL.md +0 -83
  116. package/templates/.codex/skills/result-aggregation/SKILL.md +0 -164
  117. package/templates/.codex/skills/rust-best-practices/SKILL.md +0 -267
  118. package/templates/.codex/skills/sauron-watch/SKILL.md +0 -144
  119. package/templates/.codex/skills/secretary-routing/SKILL.md +0 -203
  120. package/templates/.codex/skills/snowflake-best-practices/SKILL.md +0 -65
  121. package/templates/.codex/skills/spark-best-practices/SKILL.md +0 -52
  122. package/templates/.codex/skills/springboot-best-practices/SKILL.md +0 -218
  123. package/templates/.codex/skills/status/SKILL.md +0 -153
  124. package/templates/.codex/skills/supabase-postgres-best-practices/SKILL.md +0 -99
  125. package/templates/.codex/skills/typescript-best-practices/SKILL.md +0 -321
  126. package/templates/.codex/skills/update-docs/SKILL.md +0 -140
  127. package/templates/.codex/skills/update-external/SKILL.md +0 -149
  128. package/templates/.codex/skills/vercel-deploy/SKILL.md +0 -73
  129. package/templates/.codex/skills/web-design-guidelines/SKILL.md +0 -118
  130. package/templates/.codex/skills/writing-clearly-and-concisely/SKILL.md +0 -64
  131. package/templates/.codex/uninstall-hooks.sh +0 -52
  132. package/templates/AGENTS.md.en +0 -39
  133. package/templates/AGENTS.md.ko +0 -39
  134. package/templates/manifest.codex.json +0 -43
@@ -1,270 +0,0 @@
1
- ---
2
- name: fastapi-best-practices
3
- description: FastAPI patterns for high-performance async APIs
4
- user-invocable: false
5
- ---
6
-
7
- ## Purpose
8
-
9
- Apply FastAPI patterns for building high-performance async APIs.
10
-
11
- ## Rules
12
-
13
- ### 1. Project Structure
14
-
15
- ```yaml
16
- structure:
17
- domain_based: true
18
- module_contents:
19
- - router.py: API endpoints
20
- - schemas.py: Pydantic models
21
- - models.py: Database models
22
- - service.py: Business logic
23
- - dependencies.py: Route validators
24
- - constants.py: Module constants
25
- - config.py: Module configuration
26
- - exceptions.py: Custom exceptions
27
- - utils.py: Helper functions
28
-
29
- imports:
30
- style: explicit
31
- example: "from src.auth import constants as auth_constants"
32
-
33
- layout: |
34
- src/
35
- ├── auth/
36
- │ ├── router.py
37
- │ ├── schemas.py
38
- │ ├── models.py
39
- │ ├── service.py
40
- │ └── dependencies.py
41
- ├── users/
42
- │ └── ...
43
- ├── config.py
44
- └── main.py
45
- ```
46
-
47
- ### 2. Async Patterns
48
-
49
- ```yaml
50
- io_intensive:
51
- use: "async def"
52
- await: "asyncio.sleep(), httpx, asyncpg, etc."
53
- example: |
54
- async def fetch_data():
55
- async with httpx.AsyncClient() as client:
56
- response = await client.get(url)
57
- return response.json()
58
-
59
- sync_io:
60
- use: "def (regular function)"
61
- reason: FastAPI offloads to threadpool automatically
62
- example: |
63
- def read_file():
64
- with open('file.txt') as f:
65
- return f.read()
66
-
67
- cpu_intensive:
68
- avoid: async and threadpool
69
- use: separate worker processes
70
- example: "Use Celery or multiprocessing"
71
-
72
- never:
73
- - "time.sleep() in async functions"
74
- - "Blocking I/O in async functions"
75
- ```
76
-
77
- ### 3. Pydantic Models
78
-
79
- ```yaml
80
- validation:
81
- use_builtin: regex, enums, email, URL validators
82
- custom_validators: for complex logic
83
-
84
- base_model:
85
- create_custom: true
86
- purpose: enforce application-wide standards
87
- example: |
88
- from pydantic import BaseModel
89
- from datetime import datetime
90
-
91
- class AppBaseModel(BaseModel):
92
- class Config:
93
- from_attributes = True
94
- json_encoders = {
95
- datetime: lambda v: v.isoformat()
96
- }
97
-
98
- settings:
99
- split: across modules
100
- avoid: single global configuration
101
- example: |
102
- # auth/config.py
103
- class AuthSettings(BaseSettings):
104
- jwt_secret: str
105
- jwt_algorithm: str = "HS256"
106
-
107
- # database/config.py
108
- class DatabaseSettings(BaseSettings):
109
- url: str
110
- pool_size: int = 5
111
- ```
112
-
113
- ### 4. Dependencies
114
-
115
- ```yaml
116
- usage:
117
- - Dependency injection
118
- - Validation against database
119
- - Authentication/authorization
120
- - Request scoped caching
121
-
122
- patterns:
123
- chain: avoid code repetition
124
- cache: FastAPI caches within request scope
125
- decouple: small, reusable functions
126
-
127
- example: |
128
- async def get_current_user(
129
- token: str = Depends(oauth2_scheme),
130
- db: Session = Depends(get_db)
131
- ) -> User:
132
- user = await db.get_user_by_token(token)
133
- if not user:
134
- raise HTTPException(status_code=401)
135
- return user
136
-
137
- async def get_active_user(
138
- user: User = Depends(get_current_user)
139
- ) -> User:
140
- if not user.is_active:
141
- raise HTTPException(status_code=403)
142
- return user
143
- ```
144
-
145
- ### 5. Error Handling
146
-
147
- ```yaml
148
- custom_exceptions:
149
- scope: module-specific
150
- purpose: clarity and consistency
151
-
152
- pattern: |
153
- # auth/exceptions.py
154
- class AuthException(Exception):
155
- pass
156
-
157
- class InvalidCredentials(AuthException):
158
- pass
159
-
160
- class TokenExpired(AuthException):
161
- pass
162
-
163
- # auth/router.py
164
- @router.post("/login")
165
- async def login(credentials: LoginSchema):
166
- try:
167
- return await auth_service.login(credentials)
168
- except InvalidCredentials:
169
- raise HTTPException(
170
- status_code=401,
171
- detail="Invalid credentials"
172
- )
173
-
174
- exception_handlers: |
175
- @app.exception_handler(AuthException)
176
- async def auth_exception_handler(request, exc):
177
- return JSONResponse(
178
- status_code=401,
179
- content={"detail": str(exc)}
180
- )
181
- ```
182
-
183
- ### 6. Database
184
-
185
- ```yaml
186
- naming:
187
- establish: upfront conventions
188
- consistency: across all models
189
-
190
- migrations:
191
- tool: Alembic
192
- naming: explicit naming rules
193
-
194
- design:
195
- approach: SQL-first
196
- then: add Pydantic models
197
-
198
- patterns: |
199
- # Use async database drivers
200
- from sqlalchemy.ext.asyncio import AsyncSession
201
-
202
- async def get_user(db: AsyncSession, user_id: int):
203
- result = await db.execute(
204
- select(User).where(User.id == user_id)
205
- )
206
- return result.scalar_one_or_none()
207
- ```
208
-
209
- ### 7. API Design
210
-
211
- ```yaml
212
- routing:
213
- prefix: meaningful module prefix
214
- tags: for documentation grouping
215
-
216
- responses:
217
- schema: always define response models
218
- status_codes: document all possible codes
219
-
220
- example: |
221
- router = APIRouter(
222
- prefix="/users",
223
- tags=["users"]
224
- )
225
-
226
- @router.get(
227
- "/{user_id}",
228
- response_model=UserResponse,
229
- responses={
230
- 404: {"model": ErrorResponse}
231
- }
232
- )
233
- async def get_user(user_id: int):
234
- ...
235
- ```
236
-
237
- ### 8. Testing
238
-
239
- ```yaml
240
- setup:
241
- async_client: from day one
242
- structure: mirror module layout
243
-
244
- patterns: |
245
- import pytest
246
- from httpx import AsyncClient
247
-
248
- @pytest.fixture
249
- async def client():
250
- async with AsyncClient(app=app, base_url="http://test") as ac:
251
- yield ac
252
-
253
- @pytest.mark.asyncio
254
- async def test_get_user(client):
255
- response = await client.get("/users/1")
256
- assert response.status_code == 200
257
- ```
258
-
259
- ## Application
260
-
261
- When writing FastAPI code:
262
-
263
- 1. **Always** use domain-based project structure
264
- 2. **Always** use `async def` for I/O operations
265
- 3. **Prefer** Pydantic for all validation
266
- 4. **Use** dependencies for reusable logic
267
- 5. **Define** module-specific exceptions
268
- 6. **Document** API with response models
269
- 7. **Test** with async client
270
- 8. **Use** Ruff for code quality
@@ -1,107 +0,0 @@
1
- ---
2
- name: fix-refs
3
- description: Fix broken agent references and symlinks
4
- argument-hint: "[agent-name] [--all] [--dry-run]"
5
- disable-model-invocation: true
6
- ---
7
-
8
- # Fix References Skill
9
-
10
- Fix broken references, missing symlinks, and other agent dependency issues.
11
-
12
- ## Options
13
-
14
- ```
15
- --all, -a Fix all agents
16
- --dry-run Show what would be fixed
17
- --verbose, -v Show detailed actions
18
- ```
19
-
20
- ## Workflow
21
-
22
- ```
23
- 1. Run mgr-supplier:audit to identify issues
24
-
25
- 2. Fix issues:
26
- ├── Missing skill references → Add
27
- ├── Missing guide references → Add
28
- ├── Broken paths → Update
29
- └── Invalid references → Remove
30
-
31
- 3. Validate fixes
32
- └── Re-run mgr-supplier:audit
33
- ```
34
-
35
- ## Fixable Issues
36
-
37
- | Issue | Action |
38
- |-------|--------|
39
- | Missing skill ref | Add to agent .md file |
40
- | Missing guide ref | Add to agent .md file |
41
- | Broken path | Update path in agent .md file |
42
- | Invalid reference | Remove from agent .md file |
43
-
44
- ## Output Format
45
-
46
- ### Dry Run
47
- ```
48
- [mgr-supplier:fix lang-kotlin-expert --dry-run]
49
-
50
- Analyzing: lang-kotlin-expert
51
-
52
- Issues found:
53
- 1. Missing guide reference: kotlin
54
-
55
- Proposed fixes:
56
- 1. Add guide reference to .codex/agents/lang-kotlin-expert.md
57
-
58
- No changes made (dry-run mode).
59
- Run without --dry-run to apply fixes.
60
- ```
61
-
62
- ### Fix Mode
63
- ```
64
- [mgr-supplier:fix lang-kotlin-expert]
65
-
66
- Fixing: lang-kotlin-expert
67
-
68
- [1/2] Adding missing reference...
69
- Updating: .codex/agents/lang-kotlin-expert.md
70
- ✓ Guide reference added
71
-
72
- [2/2] Validating...
73
- Running mgr-supplier:audit...
74
- ✓ All dependencies valid
75
-
76
- Summary:
77
- Fixed: 1 issue
78
- Status: HEALTHY
79
-
80
- Agent lang-kotlin-expert is now healthy.
81
- ```
82
-
83
- ### Fix All
84
- ```
85
- [mgr-supplier:fix --all]
86
-
87
- Scanning all agents for issues...
88
-
89
- Found issues in 2 agents:
90
- - lang-kotlin-expert: 1 issue
91
- - new-agent: 2 issues
92
-
93
- Fixing lang-kotlin-expert...
94
- ✓ Added guide reference: kotlin
95
-
96
- Fixing new-agent...
97
- ✓ Added skill reference: skill-a
98
- ✓ Added skill reference: skill-b
99
-
100
- Validating all agents...
101
- ✓ mgr-supplier:audit --all passed
102
-
103
- Summary:
104
- Agents fixed: 2
105
- Issues resolved: 3
106
- All agents healthy.
107
- ```
@@ -1,338 +0,0 @@
1
- ---
2
- name: go-backend-best-practices
3
- description: Go backend patterns from Uber style and standard layout
4
- user-invocable: false
5
- ---
6
-
7
- ## Purpose
8
-
9
- Apply Go backend patterns for building production-ready services.
10
-
11
- ## Rules
12
-
13
- ### 1. Project Structure (Standard Layout)
14
-
15
- ```yaml
16
- layout: |
17
- project/
18
- ├── cmd/
19
- │ └── server/
20
- │ └── main.go
21
- ├── internal/
22
- │ ├── handler/
23
- │ ├── service/
24
- │ ├── repository/
25
- │ └── model/
26
- ├── pkg/
27
- │ └── shared/
28
- ├── api/
29
- │ └── openapi.yaml
30
- ├── configs/
31
- ├── scripts/
32
- ├── Dockerfile
33
- ├── Makefile
34
- └── go.mod
35
-
36
- directories:
37
- cmd: Main applications (one per binary)
38
- internal: Private application code
39
- pkg: Library code safe for external use
40
- api: API definitions (OpenAPI, protobuf)
41
- configs: Configuration files
42
- scripts: Build and CI scripts
43
- ```
44
-
45
- ### 2. Error Handling (Uber Style)
46
-
47
- ```yaml
48
- principles:
49
- - Wrap errors with context using %w
50
- - Handle errors once (don't log AND return)
51
- - Use sentinel errors for specific conditions
52
- - Name error variables with Err prefix
53
-
54
- patterns: |
55
- // Sentinel errors
56
- var (
57
- ErrNotFound = errors.New("not found")
58
- ErrInvalidInput = errors.New("invalid input")
59
- )
60
-
61
- // Wrap with context
62
- func getUser(id string) (*User, error) {
63
- user, err := db.FindUser(id)
64
- if err != nil {
65
- return nil, fmt.Errorf("getUser %s: %w", id, err)
66
- }
67
- return user, nil
68
- }
69
-
70
- // Check specific errors
71
- if errors.Is(err, ErrNotFound) {
72
- return http.StatusNotFound
73
- }
74
- ```
75
-
76
- ### 3. Concurrency (Uber Style)
77
-
78
- ```yaml
79
- channels:
80
- size: "Use 0 (unbuffered) or 1 only"
81
- larger: "Requires careful review"
82
-
83
- goroutines:
84
- never: fire-and-forget
85
- always: wait for completion or manage lifecycle
86
-
87
- patterns: |
88
- // Wait group for goroutines
89
- func process(items []Item) error {
90
- var wg sync.WaitGroup
91
- errCh := make(chan error, 1)
92
-
93
- for _, item := range items {
94
- wg.Add(1)
95
- go func(item Item) {
96
- defer wg.Done()
97
- if err := processItem(item); err != nil {
98
- select {
99
- case errCh <- err:
100
- default:
101
- }
102
- }
103
- }(item)
104
- }
105
-
106
- wg.Wait()
107
- close(errCh)
108
- return <-errCh
109
- }
110
-
111
- // Context for cancellation
112
- func longRunningTask(ctx context.Context) error {
113
- for {
114
- select {
115
- case <-ctx.Done():
116
- return ctx.Err()
117
- default:
118
- // do work
119
- }
120
- }
121
- }
122
- ```
123
-
124
- ### 4. HTTP Server
125
-
126
- ```yaml
127
- structure:
128
- handler: HTTP layer (request/response)
129
- service: Business logic
130
- repository: Data access
131
-
132
- patterns: |
133
- // Handler with dependency injection
134
- type UserHandler struct {
135
- service UserService
136
- }
137
-
138
- func NewUserHandler(s UserService) *UserHandler {
139
- return &UserHandler{service: s}
140
- }
141
-
142
- func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
143
- id := chi.URLParam(r, "id")
144
-
145
- user, err := h.service.GetUser(r.Context(), id)
146
- if err != nil {
147
- if errors.Is(err, ErrNotFound) {
148
- http.Error(w, "user not found", http.StatusNotFound)
149
- return
150
- }
151
- http.Error(w, "internal error", http.StatusInternalServerError)
152
- return
153
- }
154
-
155
- json.NewEncoder(w).Encode(user)
156
- }
157
-
158
- // Router setup
159
- func NewRouter(h *UserHandler) *chi.Mux {
160
- r := chi.NewRouter()
161
- r.Use(middleware.Logger)
162
- r.Use(middleware.Recoverer)
163
-
164
- r.Route("/api/v1", func(r chi.Router) {
165
- r.Get("/users/{id}", h.GetUser)
166
- r.Post("/users", h.CreateUser)
167
- })
168
-
169
- return r
170
- }
171
- ```
172
-
173
- ### 5. Dependency Injection
174
-
175
- ```yaml
176
- approach: constructor injection
177
- avoid: global variables
178
-
179
- patterns: |
180
- // Service with dependencies
181
- type UserService struct {
182
- repo UserRepository
183
- cache Cache
184
- logger *slog.Logger
185
- }
186
-
187
- func NewUserService(
188
- repo UserRepository,
189
- cache Cache,
190
- logger *slog.Logger,
191
- ) *UserService {
192
- return &UserService{
193
- repo: repo,
194
- cache: cache,
195
- logger: logger,
196
- }
197
- }
198
-
199
- // Wire up in main
200
- func main() {
201
- logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
202
- db := database.New(cfg.DatabaseURL)
203
- cache := redis.New(cfg.RedisURL)
204
-
205
- repo := repository.NewUserRepository(db)
206
- service := service.NewUserService(repo, cache, logger)
207
- handler := handler.NewUserHandler(service)
208
-
209
- router := handler.NewRouter(handler)
210
- http.ListenAndServe(":8080", router)
211
- }
212
- ```
213
-
214
- ### 6. Configuration
215
-
216
- ```yaml
217
- approach:
218
- - Use environment variables
219
- - Validate at startup
220
- - Group related settings
221
-
222
- patterns: |
223
- type Config struct {
224
- Server ServerConfig
225
- Database DatabaseConfig
226
- Redis RedisConfig
227
- }
228
-
229
- type ServerConfig struct {
230
- Host string `env:"SERVER_HOST" envDefault:"0.0.0.0"`
231
- Port int `env:"SERVER_PORT" envDefault:"8080"`
232
- ReadTimeout time.Duration `env:"SERVER_READ_TIMEOUT" envDefault:"5s"`
233
- WriteTimeout time.Duration `env:"SERVER_WRITE_TIMEOUT" envDefault:"10s"`
234
- }
235
-
236
- func LoadConfig() (*Config, error) {
237
- var cfg Config
238
- if err := env.Parse(&cfg); err != nil {
239
- return nil, fmt.Errorf("parse config: %w", err)
240
- }
241
- return &cfg, nil
242
- }
243
- ```
244
-
245
- ### 7. Testing
246
-
247
- ```yaml
248
- patterns:
249
- table_driven: for comprehensive coverage
250
- interfaces: for mocking
251
- parallel: for speed
252
-
253
- example: |
254
- func TestUserService_GetUser(t *testing.T) {
255
- tests := []struct {
256
- name string
257
- userID string
258
- mock func(*MockRepository)
259
- want *User
260
- wantErr error
261
- }{
262
- {
263
- name: "success",
264
- userID: "123",
265
- mock: func(m *MockRepository) {
266
- m.EXPECT().FindByID("123").Return(&User{ID: "123"}, nil)
267
- },
268
- want: &User{ID: "123"},
269
- },
270
- {
271
- name: "not found",
272
- userID: "999",
273
- mock: func(m *MockRepository) {
274
- m.EXPECT().FindByID("999").Return(nil, ErrNotFound)
275
- },
276
- wantErr: ErrNotFound,
277
- },
278
- }
279
-
280
- for _, tt := range tests {
281
- t.Run(tt.name, func(t *testing.T) {
282
- t.Parallel()
283
- ctrl := gomock.NewController(t)
284
- repo := NewMockRepository(ctrl)
285
- tt.mock(repo)
286
-
287
- svc := NewUserService(repo, nil, slog.Default())
288
- got, err := svc.GetUser(context.Background(), tt.userID)
289
-
290
- if !errors.Is(err, tt.wantErr) {
291
- t.Errorf("got error %v, want %v", err, tt.wantErr)
292
- }
293
- if diff := cmp.Diff(tt.want, got); diff != "" {
294
- t.Errorf("mismatch (-want +got):\n%s", diff)
295
- }
296
- })
297
- }
298
- }
299
- ```
300
-
301
- ### 8. Performance (Uber Style)
302
-
303
- ```yaml
304
- guidelines:
305
- - Use strconv over fmt for conversions
306
- - Pre-allocate slices with known capacity
307
- - Avoid repeated string-to-byte conversions
308
- - Copy slices/maps at boundaries
309
-
310
- patterns: |
311
- // Pre-allocate
312
- items := make([]Item, 0, len(input))
313
-
314
- // strconv for conversions
315
- s := strconv.Itoa(n) // not fmt.Sprintf("%d", n)
316
-
317
- // Copy at boundaries
318
- func (s *Store) GetItems() []Item {
319
- s.mu.RLock()
320
- defer s.mu.RUnlock()
321
- items := make([]Item, len(s.items))
322
- copy(items, s.items)
323
- return items
324
- }
325
- ```
326
-
327
- ## Application
328
-
329
- When writing Go backend code:
330
-
331
- 1. **Always** use standard project layout
332
- 2. **Always** wrap errors with context
333
- 3. **Never** fire-and-forget goroutines
334
- 4. **Use** constructor injection
335
- 5. **Use** table-driven tests
336
- 6. **Handle** errors once
337
- 7. **Copy** data at boundaries
338
- 8. **Validate** config at startup