@qazuor/claude-code-config 0.1.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/LICENSE +21 -0
- package/README.md +1248 -0
- package/dist/bin.cjs +11886 -0
- package/dist/bin.cjs.map +1 -0
- package/dist/bin.d.cts +1 -0
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +11869 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.cjs +3887 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1325 -0
- package/dist/index.d.ts +1325 -0
- package/dist/index.js +3835 -0
- package/dist/index.js.map +1 -0
- package/package.json +86 -0
- package/templates/.log/notifications.log +1775 -0
- package/templates/agents/README.md +164 -0
- package/templates/agents/_registry.json +443 -0
- package/templates/agents/design/content-writer.md +353 -0
- package/templates/agents/design/ux-ui-designer.md +382 -0
- package/templates/agents/engineering/astro-engineer.md +293 -0
- package/templates/agents/engineering/db-drizzle-engineer.md +360 -0
- package/templates/agents/engineering/express-engineer.md +316 -0
- package/templates/agents/engineering/fastify-engineer.md +399 -0
- package/templates/agents/engineering/hono-engineer.md +263 -0
- package/templates/agents/engineering/mongoose-engineer.md +473 -0
- package/templates/agents/engineering/nestjs-engineer.md +429 -0
- package/templates/agents/engineering/nextjs-engineer.md +451 -0
- package/templates/agents/engineering/node-typescript-engineer.md +347 -0
- package/templates/agents/engineering/prisma-engineer.md +432 -0
- package/templates/agents/engineering/react-senior-dev.md +394 -0
- package/templates/agents/engineering/tanstack-start-engineer.md +447 -0
- package/templates/agents/engineering/tech-lead.md +269 -0
- package/templates/agents/product/product-functional.md +329 -0
- package/templates/agents/product/product-technical.md +578 -0
- package/templates/agents/quality/debugger.md +514 -0
- package/templates/agents/quality/qa-engineer.md +390 -0
- package/templates/agents/specialized/enrichment-agent.md +277 -0
- package/templates/agents/specialized/i18n-specialist.md +322 -0
- package/templates/agents/specialized/seo-ai-specialist.md +387 -0
- package/templates/agents/specialized/tech-writer.md +300 -0
- package/templates/code-style/.editorconfig +27 -0
- package/templates/code-style/.prettierignore +25 -0
- package/templates/code-style/.prettierrc +12 -0
- package/templates/code-style/biome.json +78 -0
- package/templates/code-style/commitlint.config.js +44 -0
- package/templates/commands/README.md +175 -0
- package/templates/commands/_registry.json +420 -0
- package/templates/commands/add-new-entity.md +211 -0
- package/templates/commands/audit/accessibility-audit.md +360 -0
- package/templates/commands/audit/performance-audit.md +290 -0
- package/templates/commands/audit/security-audit.md +231 -0
- package/templates/commands/code-check.md +127 -0
- package/templates/commands/five-why.md +225 -0
- package/templates/commands/formatting/format-markdown.md +197 -0
- package/templates/commands/git/commit.md +247 -0
- package/templates/commands/meta/create-agent.md +257 -0
- package/templates/commands/meta/create-command.md +312 -0
- package/templates/commands/meta/create-skill.md +321 -0
- package/templates/commands/meta/help.md +318 -0
- package/templates/commands/planning/check-completed-tasks.md +224 -0
- package/templates/commands/planning/cleanup-issues.md +248 -0
- package/templates/commands/planning/planning-cleanup.md +251 -0
- package/templates/commands/planning/sync-planning-github.md +133 -0
- package/templates/commands/planning/sync-todos-github.md +203 -0
- package/templates/commands/quality-check.md +211 -0
- package/templates/commands/run-tests.md +159 -0
- package/templates/commands/start-feature-plan.md +232 -0
- package/templates/commands/start-refactor-plan.md +244 -0
- package/templates/commands/sync-planning.md +176 -0
- package/templates/commands/update-docs.md +242 -0
- package/templates/docs/CHECKPOINT-SYSTEM.md +504 -0
- package/templates/docs/INDEX.md +677 -0
- package/templates/docs/RECOMMENDED-HOOKS.md +415 -0
- package/templates/docs/_registry.json +329 -0
- package/templates/docs/diagrams/README.md +220 -0
- package/templates/docs/diagrams/agent-hierarchy.mmd +55 -0
- package/templates/docs/diagrams/documentation-map.mmd +61 -0
- package/templates/docs/diagrams/tools-relationship.mmd +55 -0
- package/templates/docs/diagrams/workflow-decision-tree.mmd +38 -0
- package/templates/docs/doc-sync.md +533 -0
- package/templates/docs/examples/end-to-end-workflow.md +1505 -0
- package/templates/docs/glossary.md +495 -0
- package/templates/docs/guides/mockup-prompt-engineering.md +644 -0
- package/templates/docs/guides/mockup-setup.md +737 -0
- package/templates/docs/learnings/README.md +250 -0
- package/templates/docs/learnings/common-architectural-patterns.md +123 -0
- package/templates/docs/learnings/common-mistakes-to-avoid.md +149 -0
- package/templates/docs/learnings/markdown-formatting-standards.md +104 -0
- package/templates/docs/learnings/monorepo-command-execution.md +64 -0
- package/templates/docs/learnings/optimization-tips.md +146 -0
- package/templates/docs/learnings/planning-linear-sync-workflow.md +70 -0
- package/templates/docs/learnings/shell-compatibility-fish.md +46 -0
- package/templates/docs/learnings/test-organization-structure.md +68 -0
- package/templates/docs/mcp-installation.md +613 -0
- package/templates/docs/mcp-servers.md +989 -0
- package/templates/docs/notification-installation.md +570 -0
- package/templates/docs/quick-start.md +354 -0
- package/templates/docs/standards/architecture-patterns.md +1064 -0
- package/templates/docs/standards/atomic-commits.md +513 -0
- package/templates/docs/standards/code-standards.md +993 -0
- package/templates/docs/standards/design-standards.md +656 -0
- package/templates/docs/standards/documentation-standards.md +1160 -0
- package/templates/docs/standards/testing-standards.md +969 -0
- package/templates/docs/system-maintenance.md +604 -0
- package/templates/docs/templates/PDR-template.md +561 -0
- package/templates/docs/templates/TODOs-template.md +534 -0
- package/templates/docs/templates/tech-analysis-template.md +800 -0
- package/templates/docs/workflows/README.md +519 -0
- package/templates/docs/workflows/atomic-task-protocol.md +955 -0
- package/templates/docs/workflows/decision-tree.md +482 -0
- package/templates/docs/workflows/edge-cases.md +856 -0
- package/templates/docs/workflows/phase-1-planning.md +957 -0
- package/templates/docs/workflows/phase-2-implementation.md +896 -0
- package/templates/docs/workflows/phase-3-validation.md +792 -0
- package/templates/docs/workflows/phase-4-finalization.md +927 -0
- package/templates/docs/workflows/quick-fix-protocol.md +505 -0
- package/templates/docs/workflows/task-atomization.md +537 -0
- package/templates/docs/workflows/task-completion-protocol.md +448 -0
- package/templates/hooks/on-notification.sh +28 -0
- package/templates/schemas/checkpoint.schema.json +97 -0
- package/templates/schemas/code-registry.schema.json +84 -0
- package/templates/schemas/pdr.schema.json +314 -0
- package/templates/schemas/problems.schema.json +55 -0
- package/templates/schemas/tech-analysis.schema.json +404 -0
- package/templates/schemas/telemetry.schema.json +298 -0
- package/templates/schemas/todos.schema.json +234 -0
- package/templates/schemas/workflows.schema.json +69 -0
- package/templates/scripts/add-changelogs.sh +105 -0
- package/templates/scripts/generate-code-registry.ts +270 -0
- package/templates/scripts/health-check.sh +343 -0
- package/templates/scripts/sync-registry.sh +40 -0
- package/templates/scripts/telemetry-report.ts +36 -0
- package/templates/scripts/validate-docs.sh +224 -0
- package/templates/scripts/validate-registry.sh +225 -0
- package/templates/scripts/validate-schemas.ts +283 -0
- package/templates/scripts/validate-structure.sh +165 -0
- package/templates/scripts/worktree-cleanup.sh +81 -0
- package/templates/scripts/worktree-create.sh +63 -0
- package/templates/sessions/planning/.gitkeep +0 -0
- package/templates/sessions/planning/archived/.gitkeep +0 -0
- package/templates/settings.json +202 -0
- package/templates/settings.local.json +138 -0
- package/templates/skills/README.md +197 -0
- package/templates/skills/_registry.json +473 -0
- package/templates/skills/audit/accessibility-audit.md +309 -0
- package/templates/skills/audit/performance-audit.md +257 -0
- package/templates/skills/audit/security-audit.md +217 -0
- package/templates/skills/auth/nextauth-patterns.md +308 -0
- package/templates/skills/brand-guidelines.md +240 -0
- package/templates/skills/documentation/markdown-formatter.md +302 -0
- package/templates/skills/git/git-commit-helper.md +321 -0
- package/templates/skills/i18n/i18n-patterns.md +251 -0
- package/templates/skills/patterns/error-handling-patterns.md +242 -0
- package/templates/skills/patterns/tdd-methodology.md +342 -0
- package/templates/skills/qa/qa-criteria-validator.md +383 -0
- package/templates/skills/qa/web-app-testing.md +398 -0
- package/templates/skills/react/react-hook-form-patterns.md +359 -0
- package/templates/skills/state/redux-toolkit-patterns.md +272 -0
- package/templates/skills/state/tanstack-query-patterns.md +299 -0
- package/templates/skills/state/zustand-patterns.md +301 -0
- package/templates/skills/tech/mermaid-diagram-specialist.md +195 -0
- package/templates/skills/tech/shadcn-specialist.md +252 -0
- package/templates/skills/tech/vercel-specialist.md +297 -0
- package/templates/skills/testing/api-app-testing.md +254 -0
- package/templates/skills/testing/performance-testing.md +275 -0
- package/templates/skills/testing/security-testing.md +348 -0
- package/templates/skills/utils/add-memory.md +295 -0
- package/templates/skills/utils/json-data-auditor.md +283 -0
- package/templates/skills/utils/pdf-creator-editor.md +342 -0
- package/templates/tools/format-markdown.sh +185 -0
|
@@ -0,0 +1,993 @@
|
|
|
1
|
+
# Code Standards
|
|
2
|
+
|
|
3
|
+
This document defines the coding standards. All code must follow these rules strictly.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
<!-- markdownlint-disable MD051 -->
|
|
10
|
+
|
|
11
|
+
1. [Language Policy](#language-policy)
|
|
12
|
+
2. [TypeScript Rules](#typescript-rules)
|
|
13
|
+
3. [RO-RO Pattern](#ro-ro-pattern)
|
|
14
|
+
4. [File Organization](#file-organization)
|
|
15
|
+
5. [Naming Conventions](#naming-conventions)
|
|
16
|
+
6. [Import Organization](#import-organization)
|
|
17
|
+
7. [JSDoc Requirements](#jsdoc-requirements)
|
|
18
|
+
8. [Comments](#comments)
|
|
19
|
+
9. [Error Handling](#error-handling)
|
|
20
|
+
10. [Validation](#validation)
|
|
21
|
+
11. [Async/Await](#asyncawait)
|
|
22
|
+
12. [Code Formatting](#code-formatting)
|
|
23
|
+
|
|
24
|
+
<!-- markdownlint-enable MD051 -->
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Language Policy
|
|
29
|
+
|
|
30
|
+
### Critical Rule: English Only
|
|
31
|
+
|
|
32
|
+
**ALL code, comments, variable names, function names, JSDoc, and error messages MUST be in English.**
|
|
33
|
+
|
|
34
|
+
**Never write in Spanish in:**
|
|
35
|
+
|
|
36
|
+
- Code
|
|
37
|
+
- Comments
|
|
38
|
+
- Variable names
|
|
39
|
+
- Function names
|
|
40
|
+
- Type names
|
|
41
|
+
- JSDoc
|
|
42
|
+
- Error messages
|
|
43
|
+
- Commit messages
|
|
44
|
+
- Documentation
|
|
45
|
+
|
|
46
|
+
**Exception:**
|
|
47
|
+
|
|
48
|
+
- Chat responses to user: Spanish
|
|
49
|
+
- User-facing UI text: Spanish (in i18n files only)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## TypeScript Rules
|
|
54
|
+
|
|
55
|
+
### Type Safety
|
|
56
|
+
|
|
57
|
+
**Always enable strict mode:**
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"compilerOptions": {
|
|
62
|
+
"strict": true,
|
|
63
|
+
"noImplicitAny": true,
|
|
64
|
+
"strictNullChecks": true,
|
|
65
|
+
"strictFunctionTypes": true,
|
|
66
|
+
"strictBindCallApply": true,
|
|
67
|
+
"strictPropertyInitialization": true,
|
|
68
|
+
"noImplicitThis": true,
|
|
69
|
+
"alwaysStrict": true
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```text
|
|
73
|
+
|
|
74
|
+
### Never Use `any`
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// ❌ BAD: Using any
|
|
78
|
+
const processData = (data: any) => {
|
|
79
|
+
return data.value;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// ✅ GOOD: Use unknown with type guards
|
|
83
|
+
const processData = (data: unknown): string => {
|
|
84
|
+
if (typeof data === 'object' && data !== null && 'value' in data) {
|
|
85
|
+
return String(data.value);
|
|
86
|
+
}
|
|
87
|
+
throw new Error('Invalid data structure');
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// ✅ GOOD: Define proper types
|
|
91
|
+
type DataInput = {
|
|
92
|
+
value: string;
|
|
93
|
+
timestamp: number;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const processData = (data: DataInput): string => {
|
|
97
|
+
return data.value;
|
|
98
|
+
};
|
|
99
|
+
```text
|
|
100
|
+
|
|
101
|
+
### Always Declare Types
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// ❌ BAD: No type annotations
|
|
105
|
+
const calculate = (a, b) => {
|
|
106
|
+
return a + b;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// ✅ GOOD: Explicit types everywhere
|
|
110
|
+
type CalculateInput = {
|
|
111
|
+
a: number;
|
|
112
|
+
b: number;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
type CalculateOutput = {
|
|
116
|
+
result: number;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const calculate = ({ a, b }: CalculateInput): CalculateOutput => {
|
|
120
|
+
return { result: a + b };
|
|
121
|
+
};
|
|
122
|
+
```text
|
|
123
|
+
|
|
124
|
+
### Prefer `type` over `interface`
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// ✅ GOOD: Use type for object shapes
|
|
128
|
+
type User = {
|
|
129
|
+
id: string;
|
|
130
|
+
name: string;
|
|
131
|
+
email: string;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// ⚠️ ACCEPTABLE: Use interface only when extending
|
|
135
|
+
interface ExtendedUser extends User {
|
|
136
|
+
role: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ✅ BETTER: Use type with intersection
|
|
140
|
+
type ExtendedUser = User & {
|
|
141
|
+
role: string;
|
|
142
|
+
};
|
|
143
|
+
```text
|
|
144
|
+
|
|
145
|
+
### Use Literal and Union Types
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// ✅ GOOD: Literal types for constants
|
|
149
|
+
type Status = 'pending' | 'approved' | 'rejected';
|
|
150
|
+
|
|
151
|
+
type UserRole = 'admin' | 'host' | 'guest';
|
|
152
|
+
|
|
153
|
+
// ✅ GOOD: Union types for alternatives
|
|
154
|
+
type Result<T> =
|
|
155
|
+
| { success: true; data: T }
|
|
156
|
+
| { success: false; error: string };
|
|
157
|
+
|
|
158
|
+
// ✅ GOOD: Discriminated unions
|
|
159
|
+
type Shape =
|
|
160
|
+
| { kind: 'circle'; radius: number }
|
|
161
|
+
| { kind: 'square'; size: number }
|
|
162
|
+
| { kind: 'rectangle'; width: number; height: number };
|
|
163
|
+
```text
|
|
164
|
+
|
|
165
|
+
### Favor Immutability
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// ✅ GOOD: Use readonly
|
|
169
|
+
type Config = {
|
|
170
|
+
readonly apiUrl: string;
|
|
171
|
+
readonly timeout: number;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// ✅ GOOD: Use as const for literal values
|
|
175
|
+
const COLORS = {
|
|
176
|
+
primary: '#007bff',
|
|
177
|
+
secondary: '#6c757d',
|
|
178
|
+
} as const;
|
|
179
|
+
|
|
180
|
+
// ✅ GOOD: Readonly arrays
|
|
181
|
+
type ReadonlyUsers = readonly User[];
|
|
182
|
+
|
|
183
|
+
// ✅ GOOD: Use Readonly utility type
|
|
184
|
+
type ImmutableUser = Readonly<User>;
|
|
185
|
+
```text
|
|
186
|
+
|
|
187
|
+
### Use `import type` for Type-Only Imports
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// ✅ GOOD: Separate type imports
|
|
191
|
+
import { createUser } from './user-service';
|
|
192
|
+
import type { User, CreateUserInput } from './types';
|
|
193
|
+
|
|
194
|
+
// ❌ BAD: Mixed imports
|
|
195
|
+
import { createUser, User, CreateUserInput } from './user-service';
|
|
196
|
+
```text
|
|
197
|
+
|
|
198
|
+
### Named Exports Only (No Default Exports)
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// ❌ BAD: Default export
|
|
202
|
+
export default class UserService {}
|
|
203
|
+
|
|
204
|
+
// ✅ GOOD: Named export
|
|
205
|
+
export class UserService {}
|
|
206
|
+
|
|
207
|
+
// ❌ BAD: Default export for function
|
|
208
|
+
export default function calculateTotal() {}
|
|
209
|
+
|
|
210
|
+
// ✅ GOOD: Named export
|
|
211
|
+
export const calculateTotal = () => {};
|
|
212
|
+
```text
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## RO-RO Pattern
|
|
217
|
+
|
|
218
|
+
**All functions MUST use RO-RO (Receive Object / Return Object) pattern.**
|
|
219
|
+
|
|
220
|
+
### Basic Example
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// ❌ BAD: Positional parameters
|
|
224
|
+
const createUser = (name: string, email: string, role: string): User => {
|
|
225
|
+
// implementation
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// ✅ GOOD: RO-RO pattern
|
|
229
|
+
type CreateUserInput = {
|
|
230
|
+
name: string;
|
|
231
|
+
email: string;
|
|
232
|
+
role: string;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
type CreateUserOutput = {
|
|
236
|
+
user: User;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const createUser = ({ name, email, role }: CreateUserInput): CreateUserOutput => {
|
|
240
|
+
// implementation
|
|
241
|
+
return { user };
|
|
242
|
+
};
|
|
243
|
+
```text
|
|
244
|
+
|
|
245
|
+
### With Async Functions
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// ✅ GOOD: Async RO-RO
|
|
249
|
+
type FetchUserInput = {
|
|
250
|
+
id: string;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
type FetchUserOutput = {
|
|
254
|
+
user: User;
|
|
255
|
+
metadata: Metadata;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const fetchUser = async ({ id }: FetchUserInput): Promise<FetchUserOutput> => {
|
|
259
|
+
const user = await db.query.users.findFirst({ where: eq(users.id, id) });
|
|
260
|
+
const metadata = await getMetadata(user);
|
|
261
|
+
return { user, metadata };
|
|
262
|
+
};
|
|
263
|
+
```text
|
|
264
|
+
|
|
265
|
+
### With Optional Parameters
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
// ✅ GOOD: Optional fields in input object
|
|
269
|
+
type SearchUsersInput = {
|
|
270
|
+
query?: string;
|
|
271
|
+
page?: number;
|
|
272
|
+
pageSize?: number;
|
|
273
|
+
orderBy?: string;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
type SearchUsersOutput = {
|
|
277
|
+
users: User[];
|
|
278
|
+
pagination: PaginationInfo;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const searchUsers = ({
|
|
282
|
+
query,
|
|
283
|
+
page = 1,
|
|
284
|
+
pageSize = 20,
|
|
285
|
+
orderBy = 'createdAt'
|
|
286
|
+
}: SearchUsersInput): SearchUsersOutput => {
|
|
287
|
+
// implementation
|
|
288
|
+
};
|
|
289
|
+
```text
|
|
290
|
+
|
|
291
|
+
### Benefits of RO-RO
|
|
292
|
+
|
|
293
|
+
1. **Self-documenting**: Parameter names are visible at call site
|
|
294
|
+
2. **Easy to extend**: Add new parameters without breaking existing calls
|
|
295
|
+
3. **Easy to refactor**: Change parameter order without issues
|
|
296
|
+
4. **Better TypeScript support**: Better autocomplete and type checking
|
|
297
|
+
5. **Consistent patterns**: Same pattern across entire codebase
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## File Organization
|
|
302
|
+
|
|
303
|
+
### File Size Limits
|
|
304
|
+
|
|
305
|
+
**Maximum 500 lines per file** (excludes tests, documentation, JSON data)
|
|
306
|
+
|
|
307
|
+
If approaching limit:
|
|
308
|
+
|
|
309
|
+
- Extract utilities to separate files
|
|
310
|
+
- Split components into smaller pieces
|
|
311
|
+
- Move types to separate type files
|
|
312
|
+
- Create subdirectories for related code
|
|
313
|
+
|
|
314
|
+
### File Structure
|
|
315
|
+
|
|
316
|
+
**Typical file structure:**
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// 1. Imports (external, then internal, then types)
|
|
320
|
+
import { useState, useEffect } from 'react';
|
|
321
|
+
import { UserService } from '@repo/service-core';
|
|
322
|
+
import type { User } from '@repo/schemas';
|
|
323
|
+
|
|
324
|
+
// 2. Types (if not in separate file)
|
|
325
|
+
type ComponentProps = {
|
|
326
|
+
userId: string;
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// 3. Constants
|
|
330
|
+
const MAX_RETRY_COUNT = 3;
|
|
331
|
+
|
|
332
|
+
// 4. Helper functions (not exported)
|
|
333
|
+
const isValidUser = (user: User): boolean => {
|
|
334
|
+
return user.email.includes('@');
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
// 5. Main exports
|
|
338
|
+
export const UserComponent = ({ userId }: ComponentProps) => {
|
|
339
|
+
// implementation
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// 6. Additional exports
|
|
343
|
+
export const useUserData = (id: string) => {
|
|
344
|
+
// implementation
|
|
345
|
+
};
|
|
346
|
+
```text
|
|
347
|
+
|
|
348
|
+
### Directory Structure
|
|
349
|
+
|
|
350
|
+
```text
|
|
351
|
+
feature/
|
|
352
|
+
├── index.ts # Barrel file (exports only)
|
|
353
|
+
├── types.ts # Type definitions
|
|
354
|
+
├── constants.ts # Constants
|
|
355
|
+
├── utils.ts # Utility functions
|
|
356
|
+
├── feature.component.tsx # Main component
|
|
357
|
+
├── feature.service.ts # Business logic
|
|
358
|
+
└── feature.test.ts # Tests
|
|
359
|
+
```text
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Naming Conventions
|
|
364
|
+
|
|
365
|
+
### Variables and Functions: camelCase
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
// ✅ GOOD
|
|
369
|
+
const userName = 'John';
|
|
370
|
+
const isActive = true;
|
|
371
|
+
const getUserById = (id: string) => {};
|
|
372
|
+
const calculateTotal = () => {};
|
|
373
|
+
```text
|
|
374
|
+
|
|
375
|
+
### Classes and Types: PascalCase
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// ✅ GOOD
|
|
379
|
+
class UserService {}
|
|
380
|
+
type UserRole = 'admin' | 'host';
|
|
381
|
+
interface IUserRepository {}
|
|
382
|
+
```text
|
|
383
|
+
|
|
384
|
+
### Constants: UPPER_SNAKE_CASE
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
// ✅ GOOD
|
|
388
|
+
const MAX_RETRY_COUNT = 3;
|
|
389
|
+
const API_BASE_URL = 'https://api.example.com';
|
|
390
|
+
const DEFAULT_PAGE_SIZE = 20;
|
|
391
|
+
```text
|
|
392
|
+
|
|
393
|
+
### Booleans: Verb Prefixes
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
// ✅ GOOD
|
|
397
|
+
const isActive = true;
|
|
398
|
+
const hasPermission = false;
|
|
399
|
+
const canEdit = true;
|
|
400
|
+
const shouldUpdate = false;
|
|
401
|
+
|
|
402
|
+
// ❌ BAD
|
|
403
|
+
const active = true;
|
|
404
|
+
const permission = false;
|
|
405
|
+
```text
|
|
406
|
+
|
|
407
|
+
### Private Class Members: Leading Underscore
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// ✅ GOOD
|
|
411
|
+
class UserService {
|
|
412
|
+
private _cache: Map<string, User>;
|
|
413
|
+
|
|
414
|
+
private _clearCache(): void {
|
|
415
|
+
this._cache.clear();
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
```text
|
|
419
|
+
|
|
420
|
+
### Files
|
|
421
|
+
|
|
422
|
+
**Components**: PascalCase
|
|
423
|
+
|
|
424
|
+
```text
|
|
425
|
+
UserProfile.tsx
|
|
426
|
+
EntityCard.tsx
|
|
427
|
+
```text
|
|
428
|
+
|
|
429
|
+
**Others**: kebab-case
|
|
430
|
+
|
|
431
|
+
```text
|
|
432
|
+
user-service.ts
|
|
433
|
+
format-date.ts
|
|
434
|
+
api-client.ts
|
|
435
|
+
```text
|
|
436
|
+
|
|
437
|
+
**Tests**: Same name + `.test.ts`
|
|
438
|
+
|
|
439
|
+
```text
|
|
440
|
+
user-service.test.ts
|
|
441
|
+
format-date.test.ts
|
|
442
|
+
```text
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Import Organization
|
|
447
|
+
|
|
448
|
+
**Always organize imports in this order:**
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
// 1. External dependencies (alphabetically)
|
|
452
|
+
import { useState, useEffect } from 'react';
|
|
453
|
+
import { z } from 'zod';
|
|
454
|
+
|
|
455
|
+
// 2. Internal packages (@repo/*) (alphabetically)
|
|
456
|
+
import { UserService } from '@repo/service-core';
|
|
457
|
+
import { logger } from '@repo/logger';
|
|
458
|
+
import { userSchema } from '@repo/schemas';
|
|
459
|
+
|
|
460
|
+
// 3. Relative imports (within package)
|
|
461
|
+
import { formatDate } from '../utils/date';
|
|
462
|
+
import { Button } from './components/Button';
|
|
463
|
+
|
|
464
|
+
// 4. Types (use import type)
|
|
465
|
+
import type { User } from '@repo/schemas';
|
|
466
|
+
import type { ServiceContext } from '../types';
|
|
467
|
+
|
|
468
|
+
// 5. Styles (if applicable)
|
|
469
|
+
import './styles.css';
|
|
470
|
+
```text
|
|
471
|
+
|
|
472
|
+
### Import Rules
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
// ✅ GOOD: Import from barrel files
|
|
476
|
+
import { UserModel, EntityModel } from '@repo/db';
|
|
477
|
+
|
|
478
|
+
// ❌ BAD: Direct file imports for public API
|
|
479
|
+
import { UserModel } from '@repo/db/src/models/user.model';
|
|
480
|
+
|
|
481
|
+
// ✅ GOOD: Type-only imports
|
|
482
|
+
import type { User } from '@repo/schemas';
|
|
483
|
+
|
|
484
|
+
// ❌ BAD: Mixing value and type imports
|
|
485
|
+
import { User, createUser } from './user';
|
|
486
|
+
```text
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## JSDoc Requirements
|
|
491
|
+
|
|
492
|
+
**EVERY exported function, class, and type MUST have comprehensive JSDoc in English.**
|
|
493
|
+
|
|
494
|
+
### Function Documentation Template
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
/**
|
|
498
|
+
|
|
499
|
+
* Creates a new user account with validation and authorization checks
|
|
500
|
+
|
|
501
|
+
*
|
|
502
|
+
|
|
503
|
+
* This function validates the input data, checks if the email is already in use,
|
|
504
|
+
* hashes the password, and creates a new user record in the database.
|
|
505
|
+
|
|
506
|
+
*
|
|
507
|
+
|
|
508
|
+
* @param {Object} params - Input parameters
|
|
509
|
+
* @param {CreateUserInput} params.input - User data to create
|
|
510
|
+
* @param {string} params.input.name - User's full name
|
|
511
|
+
* @param {string} params.input.email - User's email address (must be unique)
|
|
512
|
+
* @param {string} params.input.password - User's password (will be hashed)
|
|
513
|
+
* @param {UserRole} params.input.role - User's role (admin, host, or guest)
|
|
514
|
+
* @param {User} params.currentUser - The user performing this action
|
|
515
|
+
* @returns {Promise<CreateUserOutput>} Object containing the created user and auth token
|
|
516
|
+
|
|
517
|
+
*
|
|
518
|
+
|
|
519
|
+
* @throws {ServiceError} VALIDATION_ERROR - When input validation fails
|
|
520
|
+
* @throws {ServiceError} CONFLICT - When email already exists
|
|
521
|
+
* @throws {ServiceError} FORBIDDEN - When current user lacks permissions
|
|
522
|
+
|
|
523
|
+
*
|
|
524
|
+
|
|
525
|
+
* @example
|
|
526
|
+
* ```typescript
|
|
527
|
+
* import { UserService } from '@repo/service-core';
|
|
528
|
+
* import type { CreateUserInput } from '@repo/schemas';
|
|
529
|
+
|
|
530
|
+
*
|
|
531
|
+
|
|
532
|
+
* const service = new UserService(ctx);
|
|
533
|
+
* const result = await service.createUser({
|
|
534
|
+
* input: {
|
|
535
|
+
* name: 'John Doe',
|
|
536
|
+
* email: 'john@example.com',
|
|
537
|
+
* password: 'SecureP@ssw0rd',
|
|
538
|
+
* role: 'host'
|
|
539
|
+
* },
|
|
540
|
+
* currentUser: adminUser
|
|
541
|
+
* });
|
|
542
|
+
|
|
543
|
+
*
|
|
544
|
+
|
|
545
|
+
* console.log(result.user.id); // '123e4567-e89b-12d3-a456-426614174000'
|
|
546
|
+
* console.log(result.token); // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
547
|
+
* ```
|
|
548
|
+
|
|
549
|
+
*
|
|
550
|
+
|
|
551
|
+
* @complexity O(1) database insert + O(1) hash operation
|
|
552
|
+
* @sideEffects
|
|
553
|
+
* - Creates database record in users table
|
|
554
|
+
* - Sends welcome email to user
|
|
555
|
+
* - Logs user creation event
|
|
556
|
+
|
|
557
|
+
*
|
|
558
|
+
|
|
559
|
+
* @see {@link UserService} for related operations
|
|
560
|
+
* @see {@link validateUserInput} for validation logic
|
|
561
|
+
* @see {@link hashPassword} for password hashing
|
|
562
|
+
|
|
563
|
+
*
|
|
564
|
+
|
|
565
|
+
* @since 1.0.0
|
|
566
|
+
* @version 1.2.0
|
|
567
|
+
|
|
568
|
+
*/
|
|
569
|
+
export const createUser = async ({
|
|
570
|
+
input,
|
|
571
|
+
currentUser,
|
|
572
|
+
}: CreateUserParams): Promise<CreateUserOutput> => {
|
|
573
|
+
// implementation
|
|
574
|
+
};
|
|
575
|
+
```text
|
|
576
|
+
|
|
577
|
+
### Class Documentation
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
/**
|
|
581
|
+
|
|
582
|
+
* Service for managing user accounts and authentication
|
|
583
|
+
|
|
584
|
+
*
|
|
585
|
+
|
|
586
|
+
* This service handles all user-related operations including:
|
|
587
|
+
* - User creation and registration
|
|
588
|
+
* - User profile updates
|
|
589
|
+
* - Authentication and authorization
|
|
590
|
+
* - Password management
|
|
591
|
+
* - User search and listing
|
|
592
|
+
|
|
593
|
+
*
|
|
594
|
+
|
|
595
|
+
* @extends BaseCrudService
|
|
596
|
+
* @implements IUserService
|
|
597
|
+
|
|
598
|
+
*
|
|
599
|
+
|
|
600
|
+
* @example
|
|
601
|
+
* ```typescript
|
|
602
|
+
* import { UserService } from '@repo/service-core';
|
|
603
|
+
|
|
604
|
+
*
|
|
605
|
+
|
|
606
|
+
* const service = new UserService(ctx);
|
|
607
|
+
* const user = await service.findById({ id: '123' });
|
|
608
|
+
* ```
|
|
609
|
+
|
|
610
|
+
*
|
|
611
|
+
|
|
612
|
+
* @see {@link BaseCrudService} for base CRUD operations
|
|
613
|
+
|
|
614
|
+
*/
|
|
615
|
+
export class UserService extends BaseCrudService<
|
|
616
|
+
User,
|
|
617
|
+
UserModel,
|
|
618
|
+
CreateUserSchema,
|
|
619
|
+
UpdateUserSchema,
|
|
620
|
+
SearchUserSchema
|
|
621
|
+
> {
|
|
622
|
+
/**
|
|
623
|
+
|
|
624
|
+
* Creates a new UserService instance
|
|
625
|
+
|
|
626
|
+
*
|
|
627
|
+
|
|
628
|
+
* @param {ServiceContext} ctx - Service context with database connection
|
|
629
|
+
* @param {UserModel} [model] - Optional custom model instance
|
|
630
|
+
|
|
631
|
+
*/
|
|
632
|
+
constructor(ctx: ServiceContext, model?: UserModel) {
|
|
633
|
+
super(ctx, model ?? new UserModel(ctx.db));
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
```text
|
|
637
|
+
|
|
638
|
+
### Type Documentation
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
/**
|
|
642
|
+
|
|
643
|
+
* Represents a user account in the system
|
|
644
|
+
|
|
645
|
+
*
|
|
646
|
+
|
|
647
|
+
* Users can have one of three roles:
|
|
648
|
+
* - admin: Full system access
|
|
649
|
+
* - host: Can create and manage entitys
|
|
650
|
+
* - guest: Can book entitys
|
|
651
|
+
|
|
652
|
+
*
|
|
653
|
+
|
|
654
|
+
* @property {string} id - Unique user identifier (UUID v4)
|
|
655
|
+
* @property {string} name - User's full name
|
|
656
|
+
* @property {string} email - User's email address (unique)
|
|
657
|
+
* @property {UserRole} role - User's role in the system
|
|
658
|
+
* @property {Date} createdAt - Account creation timestamp
|
|
659
|
+
* @property {Date} updatedAt - Last update timestamp
|
|
660
|
+
* @property {Date | null} deletedAt - Soft deletion timestamp (null if active)
|
|
661
|
+
|
|
662
|
+
*
|
|
663
|
+
|
|
664
|
+
* @example
|
|
665
|
+
* ```typescript
|
|
666
|
+
* const user: User = {
|
|
667
|
+
* id: '123e4567-e89b-12d3-a456-426614174000',
|
|
668
|
+
* name: 'John Doe',
|
|
669
|
+
* email: 'john@example.com',
|
|
670
|
+
* role: 'host',
|
|
671
|
+
* createdAt: new Date('2024-01-01'),
|
|
672
|
+
* updatedAt: new Date('2024-01-01'),
|
|
673
|
+
* deletedAt: null
|
|
674
|
+
* };
|
|
675
|
+
* ```
|
|
676
|
+
|
|
677
|
+
*/
|
|
678
|
+
export type User = {
|
|
679
|
+
id: string;
|
|
680
|
+
name: string;
|
|
681
|
+
email: string;
|
|
682
|
+
role: UserRole;
|
|
683
|
+
createdAt: Date;
|
|
684
|
+
updatedAt: Date;
|
|
685
|
+
deletedAt: Date | null;
|
|
686
|
+
};
|
|
687
|
+
```text
|
|
688
|
+
|
|
689
|
+
### JSDoc Tags to Use
|
|
690
|
+
|
|
691
|
+
**Required:**
|
|
692
|
+
|
|
693
|
+
- `@param` - Function parameters
|
|
694
|
+
- `@returns` - Return value
|
|
695
|
+
- `@throws` - Possible errors
|
|
696
|
+
|
|
697
|
+
**Recommended:**
|
|
698
|
+
|
|
699
|
+
- `@example` - Working code examples
|
|
700
|
+
- `@complexity` - Time/space complexity
|
|
701
|
+
- `@sideEffects` - Any side effects
|
|
702
|
+
- `@see` - Related code/docs
|
|
703
|
+
|
|
704
|
+
**Optional:**
|
|
705
|
+
|
|
706
|
+
- `@since` - Version introduced
|
|
707
|
+
- `@deprecated` - If deprecated
|
|
708
|
+
- `@version` - Current version
|
|
709
|
+
- `@author` - Author name
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
## Comments
|
|
714
|
+
|
|
715
|
+
### When to Comment
|
|
716
|
+
|
|
717
|
+
**DO comment:**
|
|
718
|
+
|
|
719
|
+
- **WHY**, not WHAT
|
|
720
|
+
- Complex algorithms
|
|
721
|
+
- Non-obvious business logic
|
|
722
|
+
- Temporary workarounds (with TODO)
|
|
723
|
+
- Performance optimizations
|
|
724
|
+
|
|
725
|
+
**DON'T comment:**
|
|
726
|
+
|
|
727
|
+
- Obvious code
|
|
728
|
+
- What the code does (code should be self-explanatory)
|
|
729
|
+
- Redundant information
|
|
730
|
+
|
|
731
|
+
### Good vs Bad Comments
|
|
732
|
+
|
|
733
|
+
```typescript
|
|
734
|
+
// ❌ BAD: Obvious comment
|
|
735
|
+
// Set the user name to John
|
|
736
|
+
const userName = 'John';
|
|
737
|
+
|
|
738
|
+
// ✅ GOOD: Explains WHY
|
|
739
|
+
// Default to 'John' when name is not provided by OAuth provider
|
|
740
|
+
const userName = oauthName ?? 'John';
|
|
741
|
+
|
|
742
|
+
// ❌ BAD: States the obvious
|
|
743
|
+
// Loop through users
|
|
744
|
+
users.forEach(user => processUser(user));
|
|
745
|
+
|
|
746
|
+
// ✅ GOOD: Explains non-obvious business logic
|
|
747
|
+
// Process users in order of registration to maintain fair queue position
|
|
748
|
+
// Newer users should not be able to jump ahead of existing waitlist
|
|
749
|
+
users.forEach(user => processUser(user));
|
|
750
|
+
```text
|
|
751
|
+
|
|
752
|
+
### TODO Comments
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
// ✅ GOOD: TODO with context
|
|
756
|
+
// TODO: Optimize this query with an index on (userId, createdAt)
|
|
757
|
+
// Current performance: ~500ms for 10k records
|
|
758
|
+
// Target performance: <50ms
|
|
759
|
+
const results = await db.query.bookings.findMany({
|
|
760
|
+
where: eq(bookings.userId, userId),
|
|
761
|
+
orderBy: desc(bookings.createdAt),
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
// TODO: Verify if we need timezone conversion here
|
|
765
|
+
// Current assumption: All dates are UTC
|
|
766
|
+
const timestamp = new Date().toISOString();
|
|
767
|
+
```text
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## Error Handling
|
|
772
|
+
|
|
773
|
+
### Use ServiceError
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
import { ServiceError, ServiceErrorCode } from '@repo/service-core';
|
|
777
|
+
|
|
778
|
+
// ✅ GOOD: Descriptive error with context
|
|
779
|
+
if (!user) {
|
|
780
|
+
throw new ServiceError(
|
|
781
|
+
'User not found',
|
|
782
|
+
ServiceErrorCode.NOT_FOUND,
|
|
783
|
+
{ userId }
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// ✅ GOOD: Validation error with details
|
|
788
|
+
if (!input.email.includes('@')) {
|
|
789
|
+
throw new ServiceError(
|
|
790
|
+
'Invalid email format',
|
|
791
|
+
ServiceErrorCode.VALIDATION_ERROR,
|
|
792
|
+
{ email: input.email }
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
```text
|
|
796
|
+
|
|
797
|
+
### API Error Responses
|
|
798
|
+
|
|
799
|
+
```typescript
|
|
800
|
+
// ✅ GOOD: Consistent error format
|
|
801
|
+
type ApiResponse<T> =
|
|
802
|
+
| { success: true; data: T }
|
|
803
|
+
| { success: false; error: { code: string; message: string } };
|
|
804
|
+
|
|
805
|
+
// In route handler
|
|
806
|
+
try {
|
|
807
|
+
const result = await service.createUser({ input, currentUser });
|
|
808
|
+
return c.json({ success: true, data: result });
|
|
809
|
+
} catch (error) {
|
|
810
|
+
if (error instanceof ServiceError) {
|
|
811
|
+
return c.json(
|
|
812
|
+
{
|
|
813
|
+
success: false,
|
|
814
|
+
error: {
|
|
815
|
+
code: error.code,
|
|
816
|
+
message: error.message,
|
|
817
|
+
},
|
|
818
|
+
},
|
|
819
|
+
error.statusCode
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
throw error; // Let global error handler catch
|
|
823
|
+
}
|
|
824
|
+
```text
|
|
825
|
+
|
|
826
|
+
---
|
|
827
|
+
|
|
828
|
+
## Validation
|
|
829
|
+
|
|
830
|
+
### Always Use Zod
|
|
831
|
+
|
|
832
|
+
```typescript
|
|
833
|
+
import { z } from 'zod';
|
|
834
|
+
|
|
835
|
+
// ✅ GOOD: Define schema
|
|
836
|
+
export const createUserSchema = z.object({
|
|
837
|
+
name: z.string().min(1).max(200),
|
|
838
|
+
email: z.string().email(),
|
|
839
|
+
password: z.string().min(8).max(100),
|
|
840
|
+
role: z.enum(['admin', 'host', 'guest']),
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// ✅ GOOD: Infer types from schema
|
|
844
|
+
export type CreateUserInput = z.infer<typeof createUserSchema>;
|
|
845
|
+
|
|
846
|
+
// ✅ GOOD: Validate in route
|
|
847
|
+
app.post(
|
|
848
|
+
'/users',
|
|
849
|
+
zValidator('json', createUserSchema),
|
|
850
|
+
async (c) => {
|
|
851
|
+
const input = c.req.valid('json');
|
|
852
|
+
// input is now typed and validated
|
|
853
|
+
}
|
|
854
|
+
);
|
|
855
|
+
```text
|
|
856
|
+
|
|
857
|
+
### Never Inline Validation
|
|
858
|
+
|
|
859
|
+
```typescript
|
|
860
|
+
// ❌ BAD: Inline validation
|
|
861
|
+
app.post('/users', async (c) => {
|
|
862
|
+
const body = await c.req.json();
|
|
863
|
+
if (!body.name || !body.email) {
|
|
864
|
+
return c.json({ error: 'Invalid input' }, 400);
|
|
865
|
+
}
|
|
866
|
+
// ...
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
// ✅ GOOD: Use Zod schema from @repo/schemas
|
|
870
|
+
import { createUserSchema } from '@repo/schemas';
|
|
871
|
+
|
|
872
|
+
app.post(
|
|
873
|
+
'/users',
|
|
874
|
+
zValidator('json', createUserSchema),
|
|
875
|
+
async (c) => {
|
|
876
|
+
const input = c.req.valid('json');
|
|
877
|
+
// ...
|
|
878
|
+
}
|
|
879
|
+
);
|
|
880
|
+
```text
|
|
881
|
+
|
|
882
|
+
---
|
|
883
|
+
|
|
884
|
+
## Async/Await
|
|
885
|
+
|
|
886
|
+
### Always Use Async/Await (Not Promises)
|
|
887
|
+
|
|
888
|
+
```typescript
|
|
889
|
+
// ❌ BAD: Using .then()
|
|
890
|
+
const fetchUser = (id: string) => {
|
|
891
|
+
return db.query.users.findFirst({ where: eq(users.id, id) })
|
|
892
|
+
.then(user => processUser(user))
|
|
893
|
+
.then(result => result)
|
|
894
|
+
.catch(error => handleError(error));
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// ✅ GOOD: Using async/await
|
|
898
|
+
const fetchUser = async (id: string) => {
|
|
899
|
+
try {
|
|
900
|
+
const user = await db.query.users.findFirst({ where: eq(users.id, id) });
|
|
901
|
+
const result = await processUser(user);
|
|
902
|
+
return result;
|
|
903
|
+
} catch (error) {
|
|
904
|
+
handleError(error);
|
|
905
|
+
throw error;
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
```text
|
|
909
|
+
|
|
910
|
+
### Parallel Execution When Possible
|
|
911
|
+
|
|
912
|
+
```typescript
|
|
913
|
+
// ❌ BAD: Sequential when could be parallel
|
|
914
|
+
const user = await fetchUser(userId);
|
|
915
|
+
const bookings = await fetchBookings(userId);
|
|
916
|
+
const reviews = await fetchReviews(userId);
|
|
917
|
+
|
|
918
|
+
// ✅ GOOD: Parallel execution
|
|
919
|
+
const [user, bookings, reviews] = await Promise.all([
|
|
920
|
+
fetchUser(userId),
|
|
921
|
+
fetchBookings(userId),
|
|
922
|
+
fetchReviews(userId),
|
|
923
|
+
]);
|
|
924
|
+
```text
|
|
925
|
+
|
|
926
|
+
---
|
|
927
|
+
|
|
928
|
+
## Code Formatting
|
|
929
|
+
|
|
930
|
+
### Use Biome
|
|
931
|
+
|
|
932
|
+
```bash
|
|
933
|
+
|
|
934
|
+
# Check formatting and linting
|
|
935
|
+
|
|
936
|
+
pnpm check
|
|
937
|
+
|
|
938
|
+
# Auto-fix issues
|
|
939
|
+
|
|
940
|
+
pnpm check --apply
|
|
941
|
+
```text
|
|
942
|
+
|
|
943
|
+
### Key Formatting Rules
|
|
944
|
+
|
|
945
|
+
```typescript
|
|
946
|
+
// ✅ GOOD: Single quotes
|
|
947
|
+
const name = 'John';
|
|
948
|
+
|
|
949
|
+
// ✅ GOOD: Trailing commas
|
|
950
|
+
const obj = {
|
|
951
|
+
name: 'John',
|
|
952
|
+
age: 30,
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
// ✅ GOOD: 2 space indentation
|
|
956
|
+
const fn = () => {
|
|
957
|
+
if (condition) {
|
|
958
|
+
doSomething();
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
// ✅ GOOD: Semicolons
|
|
963
|
+
const x = 5;
|
|
964
|
+
|
|
965
|
+
// ✅ GOOD: Line length max 100 characters
|
|
966
|
+
const longString =
|
|
967
|
+
'This is a very long string that would exceed 100 characters so we break it';
|
|
968
|
+
```text
|
|
969
|
+
|
|
970
|
+
---
|
|
971
|
+
|
|
972
|
+
## Summary Checklist
|
|
973
|
+
|
|
974
|
+
Before committing code, verify:
|
|
975
|
+
|
|
976
|
+
- [ ] All code, comments, and JSDoc in English
|
|
977
|
+
- [ ] No `any` types used
|
|
978
|
+
- [ ] All functions use RO-RO pattern
|
|
979
|
+
- [ ] All exports are named (no default)
|
|
980
|
+
- [ ] Files under 500 lines
|
|
981
|
+
- [ ] Proper naming conventions
|
|
982
|
+
- [ ] Imports organized correctly
|
|
983
|
+
- [ ] Comprehensive JSDoc on all exports
|
|
984
|
+
- [ ] Comments explain WHY, not WHAT
|
|
985
|
+
- [ ] Zod validation for all inputs
|
|
986
|
+
- [ ] Async/await instead of promises
|
|
987
|
+
- [ ] Code formatted with Biome
|
|
988
|
+
- [ ] Type safety everywhere
|
|
989
|
+
|
|
990
|
+
---
|
|
991
|
+
|
|
992
|
+
**These standards are mandatory. Code that doesn't follow them will be rejected in code review.**
|
|
993
|
+
|