red64-cli 0.3.0 → 0.6.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/README.md +194 -338
- package/dist/cli/parseArgs.d.ts.map +1 -1
- package/dist/cli/parseArgs.js +5 -13
- package/dist/cli/parseArgs.js.map +1 -1
- package/dist/components/init/types.d.ts +0 -2
- package/dist/components/init/types.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.d.ts.map +1 -1
- package/dist/components/screens/HelpScreen.js +0 -2
- package/dist/components/screens/HelpScreen.js.map +1 -1
- package/dist/components/screens/InitScreen.d.ts.map +1 -1
- package/dist/components/screens/InitScreen.js +5 -8
- package/dist/components/screens/InitScreen.js.map +1 -1
- package/dist/components/screens/StartScreen.d.ts.map +1 -1
- package/dist/components/screens/StartScreen.js +29 -8
- package/dist/components/screens/StartScreen.js.map +1 -1
- package/dist/components/screens/StatusScreen.d.ts.map +1 -1
- package/dist/components/screens/StatusScreen.js +16 -1
- package/dist/components/screens/StatusScreen.js.map +1 -1
- package/dist/services/AgentInvoker.d.ts.map +1 -1
- package/dist/services/AgentInvoker.js +76 -37
- package/dist/services/AgentInvoker.js.map +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts +1 -1
- package/dist/services/ClaudeErrorDetector.d.ts.map +1 -1
- package/dist/services/ClaudeErrorDetector.js +1 -0
- package/dist/services/ClaudeErrorDetector.js.map +1 -1
- package/dist/services/ClaudeHealthCheck.d.ts +7 -0
- package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
- package/dist/services/ClaudeHealthCheck.js +76 -12
- package/dist/services/ClaudeHealthCheck.js.map +1 -1
- package/dist/services/ConfigService.d.ts +1 -0
- package/dist/services/ConfigService.d.ts.map +1 -1
- package/dist/services/ConfigService.js.map +1 -1
- package/dist/services/DockerRunner.js +1 -1
- package/dist/services/DockerRunner.js.map +1 -1
- package/dist/services/PhaseExecutor.d.ts.map +1 -1
- package/dist/services/PhaseExecutor.js +2 -1
- package/dist/services/PhaseExecutor.js.map +1 -1
- package/dist/services/TaskRunner.d.ts.map +1 -1
- package/dist/services/TaskRunner.js +2 -1
- package/dist/services/TaskRunner.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/framework/stacks/c/code-quality.md +326 -0
- package/framework/stacks/c/coding-style.md +347 -0
- package/framework/stacks/c/conventions.md +513 -0
- package/framework/stacks/c/error-handling.md +350 -0
- package/framework/stacks/c/feedback.md +158 -0
- package/framework/stacks/c/memory-safety.md +408 -0
- package/framework/stacks/c/tech.md +122 -0
- package/framework/stacks/c/testing.md +472 -0
- package/framework/stacks/cpp/code-quality.md +282 -0
- package/framework/stacks/cpp/coding-style.md +363 -0
- package/framework/stacks/cpp/conventions.md +420 -0
- package/framework/stacks/cpp/error-handling.md +264 -0
- package/framework/stacks/cpp/feedback.md +104 -0
- package/framework/stacks/cpp/memory-safety.md +351 -0
- package/framework/stacks/cpp/tech.md +160 -0
- package/framework/stacks/cpp/testing.md +323 -0
- package/framework/stacks/java/code-quality.md +357 -0
- package/framework/stacks/java/coding-style.md +400 -0
- package/framework/stacks/java/conventions.md +437 -0
- package/framework/stacks/java/error-handling.md +408 -0
- package/framework/stacks/java/feedback.md +180 -0
- package/framework/stacks/java/tech.md +126 -0
- package/framework/stacks/java/testing.md +485 -0
- package/framework/stacks/javascript/async-patterns.md +216 -0
- package/framework/stacks/javascript/code-quality.md +182 -0
- package/framework/stacks/javascript/coding-style.md +293 -0
- package/framework/stacks/javascript/conventions.md +268 -0
- package/framework/stacks/javascript/error-handling.md +216 -0
- package/framework/stacks/javascript/feedback.md +80 -0
- package/framework/stacks/javascript/tech.md +114 -0
- package/framework/stacks/javascript/testing.md +209 -0
- package/framework/stacks/loco/code-quality.md +156 -0
- package/framework/stacks/loco/coding-style.md +247 -0
- package/framework/stacks/loco/error-handling.md +225 -0
- package/framework/stacks/loco/feedback.md +35 -0
- package/framework/stacks/loco/loco.md +342 -0
- package/framework/stacks/loco/structure.md +193 -0
- package/framework/stacks/loco/tech.md +129 -0
- package/framework/stacks/loco/testing.md +211 -0
- package/framework/stacks/rust/code-quality.md +370 -0
- package/framework/stacks/rust/coding-style.md +475 -0
- package/framework/stacks/rust/conventions.md +430 -0
- package/framework/stacks/rust/error-handling.md +399 -0
- package/framework/stacks/rust/feedback.md +152 -0
- package/framework/stacks/rust/memory-safety.md +398 -0
- package/framework/stacks/rust/tech.md +121 -0
- package/framework/stacks/rust/testing.md +528 -0
- package/package.json +14 -2
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Code Quality Standards
|
|
2
|
+
|
|
3
|
+
Project memory for code quality conventions, linting, formatting, and security in JavaScript/Node.js.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Automate everything**: Machines enforce style; humans review logic
|
|
10
|
+
- **Fail fast in CI**: Quality gates catch issues before review
|
|
11
|
+
- **Single source of truth**: Configuration in project root, not scattered files
|
|
12
|
+
- **Fast feedback**: Sub-second lint and format checks
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Linting with ESLint (Flat Config)
|
|
17
|
+
|
|
18
|
+
### Configuration (`eslint.config.js`)
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
import js from '@eslint/js';
|
|
22
|
+
import globals from 'globals';
|
|
23
|
+
import security from 'eslint-plugin-security';
|
|
24
|
+
|
|
25
|
+
export default [
|
|
26
|
+
{ ignores: ['dist/', 'coverage/', 'node_modules/'] },
|
|
27
|
+
|
|
28
|
+
js.configs.recommended,
|
|
29
|
+
|
|
30
|
+
{
|
|
31
|
+
files: ['**/*.js'],
|
|
32
|
+
languageOptions: {
|
|
33
|
+
ecmaVersion: 'latest',
|
|
34
|
+
sourceType: 'module',
|
|
35
|
+
globals: { ...globals.node },
|
|
36
|
+
},
|
|
37
|
+
rules: {
|
|
38
|
+
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
39
|
+
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
40
|
+
'no-var': 'error',
|
|
41
|
+
'prefer-const': 'error',
|
|
42
|
+
'eqeqeq': ['error', 'always', { null: 'ignore' }],
|
|
43
|
+
'no-throw-literal': 'error',
|
|
44
|
+
'prefer-arrow-callback': 'error',
|
|
45
|
+
'prefer-template': 'error',
|
|
46
|
+
'object-shorthand': 'error',
|
|
47
|
+
'no-param-reassign': 'error',
|
|
48
|
+
'no-async-promise-executor': 'error',
|
|
49
|
+
'no-await-in-loop': 'warn',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
files: ['src/**/*.js'],
|
|
55
|
+
plugins: { security },
|
|
56
|
+
rules: { ...security.configs.recommended.rules },
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
files: ['tests/**/*.js', '**/*.test.js'],
|
|
61
|
+
rules: { 'no-unused-vars': 'off', 'no-console': 'off' },
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Formatting with Prettier
|
|
69
|
+
|
|
70
|
+
### Configuration (`.prettierrc`)
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"semi": true,
|
|
75
|
+
"singleQuote": true,
|
|
76
|
+
"trailingComma": "all",
|
|
77
|
+
"printWidth": 100,
|
|
78
|
+
"tabWidth": 2,
|
|
79
|
+
"arrowParens": "always",
|
|
80
|
+
"endOfLine": "lf"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Biome (Alternative to ESLint + Prettier)
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
|
|
91
|
+
"organizeImports": { "enabled": true },
|
|
92
|
+
"linter": { "enabled": true, "rules": { "recommended": true } },
|
|
93
|
+
"formatter": { "enabled": true, "indentStyle": "space", "indentWidth": 2, "lineWidth": 100 },
|
|
94
|
+
"files": { "ignore": ["dist/", "coverage/", "node_modules/"] }
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**When to use Biome**: Single tool, Rust-based speed, zero-config. Ideal for new projects.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Git Hooks with Husky + lint-staged
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"lint-staged": {
|
|
107
|
+
"*.js": ["eslint --fix", "prettier --write"],
|
|
108
|
+
"*.{json,md,yml,yaml}": ["prettier --write"]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Code Coverage (Vitest)
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// vitest.config.js
|
|
119
|
+
import { defineConfig } from 'vitest/config';
|
|
120
|
+
|
|
121
|
+
export default defineConfig({
|
|
122
|
+
test: {
|
|
123
|
+
coverage: {
|
|
124
|
+
provider: 'v8',
|
|
125
|
+
reporter: ['text', 'lcov', 'html'],
|
|
126
|
+
include: ['src/**/*.js'],
|
|
127
|
+
exclude: ['src/**/*.test.js', 'src/**/index.js'],
|
|
128
|
+
thresholds: { lines: 80, functions: 80, branches: 75, statements: 80 },
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Security
|
|
137
|
+
|
|
138
|
+
### Dependency Auditing
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pnpm audit
|
|
142
|
+
npm audit
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### ESLint Security Plugin
|
|
146
|
+
|
|
147
|
+
| Rule | Catches |
|
|
148
|
+
|------|---------|
|
|
149
|
+
| `security/detect-object-injection` | Prototype pollution via dynamic keys |
|
|
150
|
+
| `security/detect-non-literal-regexp` | ReDoS |
|
|
151
|
+
| `security/detect-eval-with-expression` | Code injection via `eval()` |
|
|
152
|
+
| `security/detect-non-literal-fs-filename` | Path traversal attacks |
|
|
153
|
+
|
|
154
|
+
### Additional Practices
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// GOOD: Parameterized queries
|
|
158
|
+
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
159
|
+
|
|
160
|
+
// BAD: String interpolation in queries
|
|
161
|
+
const user = await db.query(`SELECT * FROM users WHERE id = ${userId}`);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Quality Commands Summary
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# Full quality check (CI)
|
|
170
|
+
npx eslint .
|
|
171
|
+
npx prettier --check .
|
|
172
|
+
npx vitest run --coverage
|
|
173
|
+
npm audit
|
|
174
|
+
|
|
175
|
+
# Development
|
|
176
|
+
npx eslint . --fix && npx prettier --write .
|
|
177
|
+
npx vitest run tests/unit/ --reporter=dot
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
_Focus on patterns over exhaustive rules. Code should be linted, formatted, tested, and audited._
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# JavaScript Coding Style
|
|
2
|
+
|
|
3
|
+
Coding style conventions beyond what ESLint and Prettier enforce automatically. Opinionated patterns for readable, maintainable JavaScript.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Readability counts**: Code is read far more than written
|
|
10
|
+
- **Modern syntax**: Use ES2024+ features; do not write ES5-era code
|
|
11
|
+
- **Consistency over preference**: Follow the project convention, not personal style
|
|
12
|
+
- **Automate what you can**: Let ESLint and Prettier handle formatting; this doc covers judgment calls
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Naming Conventions
|
|
17
|
+
|
|
18
|
+
### Standard JavaScript Naming
|
|
19
|
+
|
|
20
|
+
| Element | Convention | Example |
|
|
21
|
+
|---------|-----------|---------|
|
|
22
|
+
| Variables, functions | `camelCase` | `userCount`, `getUser` |
|
|
23
|
+
| Classes | `PascalCase` | `UserService`, `AppError` |
|
|
24
|
+
| Constants | `UPPER_SNAKE_CASE` | `MAX_RETRIES`, `DEFAULT_PAGE_SIZE` |
|
|
25
|
+
| Files, modules | `kebab-case` or `camelCase` | `user-service.js`, `userService.js` |
|
|
26
|
+
| Private (convention) | `_leadingUnderscore` or `#private` | `_cache`, `#connection` |
|
|
27
|
+
| Enums (object) | `PascalCase` object, `UPPER_SNAKE_CASE` values | `Status.ACTIVE` |
|
|
28
|
+
| Environment vars | `UPPER_SNAKE_CASE` | `DATABASE_URL`, `NODE_ENV` |
|
|
29
|
+
|
|
30
|
+
### Naming Rules
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
// GOOD: Descriptive, reveals intent
|
|
34
|
+
const userCount = activeUsers.length;
|
|
35
|
+
const isAuthenticated = token !== null;
|
|
36
|
+
const MAX_RETRY_ATTEMPTS = 3;
|
|
37
|
+
|
|
38
|
+
async function getActiveUsers(db) {
|
|
39
|
+
// ...
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class PaymentProcessingError extends AppError {
|
|
43
|
+
// ...
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// BAD: Abbreviated, unclear
|
|
47
|
+
const uc = au.length;
|
|
48
|
+
const auth = token !== null;
|
|
49
|
+
const n = 3;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Boolean Naming
|
|
53
|
+
|
|
54
|
+
Prefix with `is`, `has`, `can`, `should`:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const isActive = true;
|
|
58
|
+
const hasPermission = user.roles.includes('admin');
|
|
59
|
+
const canPublish = post.status === 'draft';
|
|
60
|
+
const shouldNotify = preferences.emailEnabled;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Variable Declarations
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
// GOOD: const by default, let only when reassignment is needed
|
|
69
|
+
const users = await getUsers();
|
|
70
|
+
const config = Object.freeze({ port: 3000, host: 'localhost' });
|
|
71
|
+
|
|
72
|
+
let retryCount = 0;
|
|
73
|
+
while (retryCount < MAX_RETRIES) {
|
|
74
|
+
retryCount++;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// BAD: var (function-scoped, hoisted, error-prone)
|
|
78
|
+
var users = await getUsers(); // Never use var
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Rule**: Always use `const`. Use `let` only when the variable must be reassigned. Never use `var`.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Modern JavaScript Features
|
|
86
|
+
|
|
87
|
+
### Destructuring
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
// GOOD: Destructure objects and arrays
|
|
91
|
+
const { name, email, role = 'user' } = user;
|
|
92
|
+
const [first, ...rest] = items;
|
|
93
|
+
const { data: users, error } = await fetchUsers();
|
|
94
|
+
|
|
95
|
+
// GOOD: Parameter destructuring
|
|
96
|
+
function createUser({ name, email, password }) {
|
|
97
|
+
// ...
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Optional Chaining and Nullish Coalescing
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// GOOD: Optional chaining for safe deep access
|
|
105
|
+
const city = user?.address?.city;
|
|
106
|
+
const firstTag = post?.tags?.[0];
|
|
107
|
+
|
|
108
|
+
// GOOD: Nullish coalescing for defaults (only null/undefined)
|
|
109
|
+
const pageSize = options.pageSize ?? 20;
|
|
110
|
+
|
|
111
|
+
// BAD: Logical OR for defaults (falsy trap: 0, '', false are overridden)
|
|
112
|
+
const pageSize = options.pageSize || 20; // BUG: pageSize=0 becomes 20
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Template Literals
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
// GOOD: Template literals for string interpolation
|
|
119
|
+
const message = `User ${user.name} created with ID ${user.id}`;
|
|
120
|
+
|
|
121
|
+
// BAD: String concatenation
|
|
122
|
+
const message = 'User ' + user.name + ' created with ID ' + user.id;
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Arrow Functions vs Function Declarations
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
// GOOD: Function declarations for named, top-level functions
|
|
131
|
+
async function createUser(data) {
|
|
132
|
+
// ...
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// GOOD: Arrow functions for callbacks and short expressions
|
|
136
|
+
const activeUsers = users.filter(user => user.isActive);
|
|
137
|
+
const names = users.map(user => user.name);
|
|
138
|
+
|
|
139
|
+
// BAD: Arrow functions for complex, named functions
|
|
140
|
+
const createUser = async (data) => {
|
|
141
|
+
// 30+ lines of complex logic -- hard to find in stack traces
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Rule**: Use function declarations for named, reusable functions. Use arrow functions for callbacks and array methods.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Function Design
|
|
150
|
+
|
|
151
|
+
### Size Limits
|
|
152
|
+
|
|
153
|
+
- **Target**: Under 20 lines of logic
|
|
154
|
+
- **Maximum**: 40 lines (extract if longer)
|
|
155
|
+
- **Parameters**: Maximum 4; use an options object for more
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// GOOD: Options object for many parameters
|
|
159
|
+
async function queryUsers({ status, role, page = 1, limit = 20, sortBy = 'createdAt' } = {}) {
|
|
160
|
+
// ...
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// BAD: Too many positional parameters
|
|
164
|
+
async function queryUsers(status, role, page, limit, sortBy, sortOrder, includeDeleted) {
|
|
165
|
+
// ...
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Early Returns (Guard Clauses)
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
// GOOD: Guard clauses
|
|
173
|
+
async function publishPost(post, user) {
|
|
174
|
+
if (post.userId !== user.id) {
|
|
175
|
+
throw new AuthorizationError('Cannot publish another user\'s post');
|
|
176
|
+
}
|
|
177
|
+
if (post.status === 'published') {
|
|
178
|
+
throw new ConflictError('Already published');
|
|
179
|
+
}
|
|
180
|
+
if (!post.body) {
|
|
181
|
+
throw new ValidationError('Body required');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
post.status = 'published';
|
|
185
|
+
return postRepo.save(post);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// BAD: Deeply nested
|
|
189
|
+
async function publishPost(post, user) {
|
|
190
|
+
if (post.userId === user.id) {
|
|
191
|
+
if (post.status !== 'published') {
|
|
192
|
+
if (post.body) {
|
|
193
|
+
post.status = 'published';
|
|
194
|
+
return postRepo.save(post);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Module Organization
|
|
204
|
+
|
|
205
|
+
### ESM Module Layout
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
// 1. Node.js built-in imports
|
|
209
|
+
import { readFile } from 'node:fs/promises';
|
|
210
|
+
import { join } from 'node:path';
|
|
211
|
+
|
|
212
|
+
// 2. Third-party imports
|
|
213
|
+
import Fastify from 'fastify';
|
|
214
|
+
import { z } from 'zod';
|
|
215
|
+
|
|
216
|
+
// 3. Local imports
|
|
217
|
+
import { AppError } from './errors.js';
|
|
218
|
+
import { userService } from './services/user-service.js';
|
|
219
|
+
|
|
220
|
+
// 4. Module-level constants
|
|
221
|
+
const MAX_RETRIES = 3;
|
|
222
|
+
const DEFAULT_PAGE_SIZE = 20;
|
|
223
|
+
|
|
224
|
+
// 5. Classes and functions
|
|
225
|
+
export class UserController {
|
|
226
|
+
// ...
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Import Rules
|
|
231
|
+
|
|
232
|
+
- Always use ESM (`import/export`), never CommonJS (`require/module.exports`)
|
|
233
|
+
- Include file extensions in relative imports (`.js`)
|
|
234
|
+
- Prefix Node.js built-ins with `node:` (`import { readFile } from 'node:fs/promises'`)
|
|
235
|
+
- Group imports: built-ins, third-party, local (separated by blank lines)
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Equality and Comparisons
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// GOOD: Always use strict equality
|
|
243
|
+
if (status === 'active') { /* ... */ }
|
|
244
|
+
if (count !== 0) { /* ... */ }
|
|
245
|
+
|
|
246
|
+
// Only acceptable use of == is null check
|
|
247
|
+
if (value == null) { /* ... */ } // Checks both null and undefined
|
|
248
|
+
|
|
249
|
+
// BAD: Loose equality (type coercion traps)
|
|
250
|
+
if (status == 'active') { /* ... */ }
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Common Anti-Patterns
|
|
256
|
+
|
|
257
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| Callback hell | Pyramid of doom, hard to read | async/await |
|
|
260
|
+
| `var` declarations | Function-scoped, hoisting bugs | `const` / `let` |
|
|
261
|
+
| Implicit globals | Missing declaration pollutes global scope | Always declare variables |
|
|
262
|
+
| Mutating function arguments | Caller's object is modified | Return new object with spread |
|
|
263
|
+
| Prototype pollution | Merging untrusted input | Validate keys, use structuredClone |
|
|
264
|
+
| `||` for defaults | Falsy trap (0, '', false overridden) | Use `??` (nullish coalescing) |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## File and Class Size
|
|
269
|
+
|
|
270
|
+
| Element | Guideline |
|
|
271
|
+
|---------|-----------|
|
|
272
|
+
| Function | Under 20 lines of logic, max 40 |
|
|
273
|
+
| Class | Under 200 lines, max 300 |
|
|
274
|
+
| Module | Under 300 lines, max 500 |
|
|
275
|
+
| Parameters | Max 4 per function; use options object for more |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Formatting (Handled by Prettier)
|
|
280
|
+
|
|
281
|
+
These are automated -- do not worry about them manually:
|
|
282
|
+
|
|
283
|
+
- Line length: 100 characters
|
|
284
|
+
- Indentation: 2 spaces
|
|
285
|
+
- Semicolons: consistent (pick one, enforce it)
|
|
286
|
+
- Quote style: single quotes
|
|
287
|
+
- Trailing commas in multi-line constructs
|
|
288
|
+
|
|
289
|
+
Run `npx prettier --write .` and move on.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
_Style is a tool for communication. Write code that your future self and teammates will thank you for._
|