@newpeak/barista-cli 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/.eslintrc.json +23 -0
- package/.prettierrc +9 -0
- package/.sisyphus/notepads/liberica-employees/learnings.md +73 -0
- package/AGENTS.md +270 -0
- package/CONTRIBUTING.md +291 -0
- package/README.md +707 -0
- package/bin/barista +6 -0
- package/bin/barista.js +3 -0
- package/docs/ARCHITECTURE.md +184 -0
- package/docs/COMMANDS.md +352 -0
- package/docs/COMMAND_DESIGN_SPEC.md +811 -0
- package/docs/INTEGRATION_NOTES.md +270 -0
- package/docs/commands/REFERENCE.md +297 -0
- package/docs/commands/arabica/auth/index.md +296 -0
- package/docs/commands/liberica/auth/index.md +133 -0
- package/docs/commands/liberica/context/index.md +60 -0
- package/docs/commands/liberica/employees/create.md +185 -0
- package/docs/commands/liberica/employees/disable.md +138 -0
- package/docs/commands/liberica/employees/enable.md +137 -0
- package/docs/commands/liberica/employees/get.md +153 -0
- package/docs/commands/liberica/employees/list.md +168 -0
- package/docs/commands/liberica/employees/update.md +180 -0
- package/docs/commands/liberica/orgs/list.md +62 -0
- package/docs/commands/liberica/positions/list.md +61 -0
- package/docs/commands/liberica/roles/list.md +67 -0
- package/docs/commands/liberica/users/create.md +170 -0
- package/docs/commands/liberica/users/get.md +151 -0
- package/docs/commands/liberica/users/list.md +175 -0
- package/package.json +37 -0
- package/src/commands/arabica/auth/index.ts +277 -0
- package/src/commands/arabica/auth/login.ts +5 -0
- package/src/commands/arabica/auth/logout.ts +5 -0
- package/src/commands/arabica/auth/register.ts +5 -0
- package/src/commands/arabica/auth/status.ts +5 -0
- package/src/commands/arabica/index.ts +23 -0
- package/src/commands/auth.ts +107 -0
- package/src/commands/context.ts +60 -0
- package/src/commands/liberica/auth/index.ts +170 -0
- package/src/commands/liberica/context/index.ts +43 -0
- package/src/commands/liberica/employees/create.ts +275 -0
- package/src/commands/liberica/employees/delete.ts +122 -0
- package/src/commands/liberica/employees/disable.ts +97 -0
- package/src/commands/liberica/employees/enable.ts +97 -0
- package/src/commands/liberica/employees/get.ts +115 -0
- package/src/commands/liberica/employees/index.ts +23 -0
- package/src/commands/liberica/employees/list.ts +131 -0
- package/src/commands/liberica/employees/update.ts +157 -0
- package/src/commands/liberica/index.ts +36 -0
- package/src/commands/liberica/orgs/index.ts +35 -0
- package/src/commands/liberica/positions/index.ts +30 -0
- package/src/commands/liberica/roles/index.ts +59 -0
- package/src/commands/liberica/users/create.ts +132 -0
- package/src/commands/liberica/users/delete.ts +49 -0
- package/src/commands/liberica/users/disable.ts +41 -0
- package/src/commands/liberica/users/enable.ts +30 -0
- package/src/commands/liberica/users/get.ts +46 -0
- package/src/commands/liberica/users/index.ts +27 -0
- package/src/commands/liberica/users/list.ts +68 -0
- package/src/commands/liberica/users/me.ts +42 -0
- package/src/commands/liberica/users/reset-password.ts +42 -0
- package/src/commands/liberica/users/update.ts +48 -0
- package/src/core/api/client.ts +825 -0
- package/src/core/auth/token-manager.ts +183 -0
- package/src/core/config/manager.ts +164 -0
- package/src/index.ts +37 -0
- package/src/types/employee.ts +102 -0
- package/src/types/index.ts +75 -0
- package/src/types/org.ts +25 -0
- package/src/types/position.ts +24 -0
- package/src/types/user.ts +64 -0
- package/tests/unit/commands/arabica/auth.test.ts +230 -0
- package/tests/unit/commands/liberica/auth.test.ts +175 -0
- package/tests/unit/commands/liberica/context.test.ts +98 -0
- package/tests/unit/commands/liberica/employees/create.test.ts +463 -0
- package/tests/unit/commands/liberica/employees/disable.test.ts +82 -0
- package/tests/unit/commands/liberica/employees/enable.test.ts +82 -0
- package/tests/unit/commands/liberica/employees/get.test.ts +111 -0
- package/tests/unit/commands/liberica/employees/list.test.ts +294 -0
- package/tests/unit/commands/liberica/employees/update.test.ts +210 -0
- package/tests/unit/config.test.ts +141 -0
- package/tests/unit/types.test.ts +195 -0
- package/tsconfig.json +20 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"node": true,
|
|
4
|
+
"es2022": true
|
|
5
|
+
},
|
|
6
|
+
"extends": [
|
|
7
|
+
"eslint:recommended",
|
|
8
|
+
"plugin:@typescript-eslint/recommended"
|
|
9
|
+
],
|
|
10
|
+
"parser": "@typescript-eslint/parser",
|
|
11
|
+
"parserOptions": {
|
|
12
|
+
"ecmaVersion": 2022,
|
|
13
|
+
"sourceType": "module"
|
|
14
|
+
},
|
|
15
|
+
"plugins": ["@typescript-eslint"],
|
|
16
|
+
"rules": {
|
|
17
|
+
"no-console": "off",
|
|
18
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
19
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
20
|
+
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
|
|
21
|
+
},
|
|
22
|
+
"ignorePatterns": ["dist/", "node_modules/", "*.js"]
|
|
23
|
+
}
|
package/.prettierrc
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Liberica Employees - Learnings
|
|
2
|
+
|
|
3
|
+
## API Patterns Observed
|
|
4
|
+
|
|
5
|
+
- API expects token WITHOUT "Bearer " prefix
|
|
6
|
+
- API prefix: /api
|
|
7
|
+
- Pagination is 0-based on backend
|
|
8
|
+
- Response fields: rows, pageNo, pageSize, totalRows
|
|
9
|
+
- Backend error format: {success, code, message} directly (not nested under error object)
|
|
10
|
+
- organizationId is `string` (was BigInteger), positionId is `string`
|
|
11
|
+
|
|
12
|
+
## CRITICAL: BigInteger IDs
|
|
13
|
+
|
|
14
|
+
**Backend returns BigInteger for all ID fields, which exceeds JavaScript number range.**
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// WRONG - Precision loss for IDs > 9007199254740991
|
|
18
|
+
employeeId: number
|
|
19
|
+
|
|
20
|
+
// CORRECT
|
|
21
|
+
employeeId: string
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Affected interfaces:**
|
|
25
|
+
- Employee.employeeId
|
|
26
|
+
- Employee.organizationId
|
|
27
|
+
- UpdateEmployeeRequest.employeeId
|
|
28
|
+
- OrgListItem.id (for cached org/position lookups)
|
|
29
|
+
|
|
30
|
+
## CRITICAL: Do NOT Use X-TENANT-ID Header
|
|
31
|
+
|
|
32
|
+
The tenant is embedded in the JWT token. Passing `X-TENANT-ID` with string tenant name causes:
|
|
33
|
+
```
|
|
34
|
+
NumberFormatException: For input string: "shanghai"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Backend expects numeric tenant ID or no header at all.
|
|
38
|
+
|
|
39
|
+
## HTTP Methods Matter
|
|
40
|
+
|
|
41
|
+
| Endpoint | Method | Common Error |
|
|
42
|
+
|----------|--------|--------------|
|
|
43
|
+
| `/master/org/tree` | POST (not GET!) | A1504: 当前接口不支持GET方式请求 |
|
|
44
|
+
| `/master/position/list` | GET | - |
|
|
45
|
+
| `/employee/delete` | POST | - |
|
|
46
|
+
|
|
47
|
+
## Error Response Normalization
|
|
48
|
+
|
|
49
|
+
Backend returns errors in two formats - must normalize in handleApiError:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
// Format 1: Error at top level
|
|
53
|
+
{ success: false, code: "A150001", message: "查询结果不存在" }
|
|
54
|
+
|
|
55
|
+
// Format 2: Nested under error
|
|
56
|
+
{ success: false, error: { code: "01001150001", message: "职员不存在" } }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Implementation Decisions
|
|
60
|
+
|
|
61
|
+
- In-memory cache (Map) for org/position lists with 5-minute TTL
|
|
62
|
+
- Cache key: `${environment}:${tenant}`
|
|
63
|
+
- Generic lookup types (OrgListItem, PositionListItem) with `id` + `name` for reuse across modules
|
|
64
|
+
- Create command resolves names to IDs before building request; exits with descriptive error if not found
|
|
65
|
+
- Position ID stays as string (backend contract)
|
|
66
|
+
- All IDs use string type to handle BigInteger without precision loss
|
|
67
|
+
|
|
68
|
+
## Debugging Tips
|
|
69
|
+
|
|
70
|
+
1. Add `console.error('[DEBUG]', ...)` to see raw API responses
|
|
71
|
+
2. Use `--json` flag to get full response data with IDs
|
|
72
|
+
3. Token stored in `~/.barista/.barista-tokens` (binary format)
|
|
73
|
+
4. Config stored in `~/.barista/config.yaml`
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# AGENTS.md - Barista CLI
|
|
2
|
+
|
|
3
|
+
**Project**: Node.js CLI (TypeScript) for Liberica & Arabica services
|
|
4
|
+
**Updated**: 2025-04-13
|
|
5
|
+
|
|
6
|
+
## Quick Commands
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
cd coffee-barista-cli
|
|
10
|
+
|
|
11
|
+
npm run build # Build TypeScript
|
|
12
|
+
npm run dev # Watch mode
|
|
13
|
+
npm run test:unit # Run tests (single run)
|
|
14
|
+
npm test # Watch mode
|
|
15
|
+
npm run lint # ESLint check
|
|
16
|
+
npm run lint -- --fix # Auto-fix
|
|
17
|
+
|
|
18
|
+
# Run CLI directly
|
|
19
|
+
node ./bin/barista.js --help
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Project Structure
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
src/
|
|
26
|
+
├── index.ts # Main entry - Commander setup
|
|
27
|
+
├── commands/
|
|
28
|
+
│ ├── context.ts # Context management
|
|
29
|
+
│ ├── auth.ts # Auth commands
|
|
30
|
+
│ ├── liberica/
|
|
31
|
+
│ │ ├── index.ts # Liberica service entry
|
|
32
|
+
│ │ ├── auth/index.ts # Liberica auth
|
|
33
|
+
│ │ ├── context/index.ts # Liberica context
|
|
34
|
+
│ │ └── employees/ # Employee CRUD commands
|
|
35
|
+
│ └── arabica/
|
|
36
|
+
│ └── auth/ # Arabica auth commands
|
|
37
|
+
├── core/
|
|
38
|
+
│ ├── auth/token-manager.ts # Keychain token storage
|
|
39
|
+
│ ├── config/manager.ts # YAML config (~/.barista/config.yaml)
|
|
40
|
+
│ └── api/client.ts # API client (axios wrapper)
|
|
41
|
+
└── types/
|
|
42
|
+
├── index.ts
|
|
43
|
+
├── employee.ts
|
|
44
|
+
├── org.ts
|
|
45
|
+
└── position.ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## CRITICAL: API Integration Rules
|
|
49
|
+
|
|
50
|
+
**These rules are hard-won. Breaking them causes silent failures.**
|
|
51
|
+
|
|
52
|
+
### 1. BigInteger IDs → Use String Type
|
|
53
|
+
|
|
54
|
+
Backend returns BigInteger for all ID fields, exceeding JS `number` range (max: 9007199254740991).
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// WRONG - precision loss
|
|
58
|
+
employeeId: number
|
|
59
|
+
|
|
60
|
+
// CORRECT
|
|
61
|
+
employeeId: string
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**All ID fields from backend MUST be `string`.**
|
|
65
|
+
|
|
66
|
+
### 2. Do NOT Use X-TENANT-ID Header
|
|
67
|
+
|
|
68
|
+
Tenant is embedded in JWT token. Passing `X-TENANT-ID` causes:
|
|
69
|
+
```
|
|
70
|
+
NumberFormatException: For input string: "shanghai"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// WRONG
|
|
75
|
+
{ headers: { 'X-TENANT-ID': tenant } }
|
|
76
|
+
|
|
77
|
+
// CORRECT - omit header entirely
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Authorization: No "Bearer " Prefix
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
// WRONG
|
|
84
|
+
'Authorization': `Bearer ${token}`
|
|
85
|
+
|
|
86
|
+
// CORRECT
|
|
87
|
+
'Authorization': token
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. HTTP Methods Vary by Endpoint
|
|
91
|
+
|
|
92
|
+
Always check the backend controller for correct method:
|
|
93
|
+
|
|
94
|
+
| Endpoint | Method | Notes |
|
|
95
|
+
|----------|--------|-------|
|
|
96
|
+
| `/employee/page` | GET | Paginated list |
|
|
97
|
+
| `/employee/detail` | GET | Single item |
|
|
98
|
+
| `/employee/add\|edit\|delete` | POST | Write operations |
|
|
99
|
+
| `/master/org/tree` | POST | NOT GET |
|
|
100
|
+
| `/master/position/list` | GET | - |
|
|
101
|
+
|
|
102
|
+
### 5. Error Response Has Two Formats
|
|
103
|
+
|
|
104
|
+
Backend returns errors in different structures:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Format 1: Top-level error (common)
|
|
108
|
+
{ success: false, code: "A150001", message: "查询结果不存在" }
|
|
109
|
+
|
|
110
|
+
// Format 2: Nested under 'error'
|
|
111
|
+
{ success: false, error: { code: "01001150001", message: "职员不存在" } }
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Must normalize in `handleApiError()`.
|
|
115
|
+
|
|
116
|
+
### 6. Pagination: 0-Based, Use pageNo/pageSize
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// CLI page 1 → API page 0
|
|
120
|
+
const pageNo = parseInt(options.page) - 1;
|
|
121
|
+
// Query: /employee/page?pageNo=0&pageSize=20
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 7. Response Field Names Differ
|
|
125
|
+
|
|
126
|
+
| Backend | Common Mistake |
|
|
127
|
+
|---------|---------------|
|
|
128
|
+
| `rows` | `records` |
|
|
129
|
+
| `pageNo` | `current` |
|
|
130
|
+
| `pageSize` | `size` |
|
|
131
|
+
| `totalRows` | `total` |
|
|
132
|
+
|
|
133
|
+
## Common Issues & Fixes
|
|
134
|
+
|
|
135
|
+
| Error | Cause | Fix |
|
|
136
|
+
|-------|-------|-----|
|
|
137
|
+
| `A1504: 不支持GET方式` | Wrong HTTP method | Use POST for `/org/tree` |
|
|
138
|
+
| `NumberFormatException` | Using `X-TENANT-ID` header | Remove header |
|
|
139
|
+
| Precision loss on IDs | Using `number` for BigInteger | Use `string` |
|
|
140
|
+
| "not found" for valid ID | ID truncated due to precision loss | Use string type |
|
|
141
|
+
| Empty data despite records | Field name mismatch | Check `rows` not `records` |
|
|
142
|
+
|
|
143
|
+
## CLI Conventions
|
|
144
|
+
|
|
145
|
+
### Command Structure
|
|
146
|
+
- Factory functions: `createXxxCommand(): Command`
|
|
147
|
+
- Subcommands via `.addCommand()`
|
|
148
|
+
- Commander.js 12 (not oclif/yargs)
|
|
149
|
+
|
|
150
|
+
### Output Formatting
|
|
151
|
+
- TTY auto-detection: tables for humans, JSON for scripts
|
|
152
|
+
- `--json` flag forces JSON output
|
|
153
|
+
- `chalk` for colors, `cli-table3` for tables
|
|
154
|
+
|
|
155
|
+
### Imports
|
|
156
|
+
- Use `.js` extension even in TypeScript: `'../../core/config/manager.js'`
|
|
157
|
+
- Async parse: `program.parseAsync()` not `parse()`
|
|
158
|
+
|
|
159
|
+
## Token & Config
|
|
160
|
+
|
|
161
|
+
- Tokens: System keychain only (keytar), NOT files
|
|
162
|
+
- Key: `{service}:{environment}:{tenant}` (e.g., `liberica:dev:shanghai`)
|
|
163
|
+
- Config: `~/.barista/config.yaml`
|
|
164
|
+
- First run creates config with defaults
|
|
165
|
+
|
|
166
|
+
## Adding Commands (MANDATORY: Design First)
|
|
167
|
+
|
|
168
|
+
1. Read `docs/COMMAND_DESIGN_SPEC.md`
|
|
169
|
+
2. Find backend Controller endpoints (check facade modules)
|
|
170
|
+
3. Create design doc at `docs/commands/{service}/{resource}/{action}.md`
|
|
171
|
+
4. Implement following existing patterns
|
|
172
|
+
5. Write unit tests
|
|
173
|
+
6. Verify: `npm run build && npm run test:unit`
|
|
174
|
+
|
|
175
|
+
## Functional Verification Workflow
|
|
176
|
+
|
|
177
|
+
**Always verify new commands against the real API before committing.**
|
|
178
|
+
|
|
179
|
+
### Standard Test Environment
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Environment: dev
|
|
183
|
+
# Tenant: shanghai
|
|
184
|
+
# User: admin@shanghai.newpeaksh.com
|
|
185
|
+
# Password: 123456
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Workflow
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
cd coffee-barista-cli
|
|
192
|
+
|
|
193
|
+
# 1. Build
|
|
194
|
+
npm run build
|
|
195
|
+
|
|
196
|
+
# 2. Login to Liberica
|
|
197
|
+
node ./bin/barista.js liberica auth login dev shanghai admin@shanghai.newpeaksh.com 123456
|
|
198
|
+
|
|
199
|
+
# 3. Verify login
|
|
200
|
+
node ./bin/barista.js context show
|
|
201
|
+
|
|
202
|
+
# 4. Test command (use --json to see full IDs)
|
|
203
|
+
node ./bin/barista.js liberica employees list --json
|
|
204
|
+
|
|
205
|
+
# 5. Test specific operations
|
|
206
|
+
node ./bin/barista.js liberica employees get <id>
|
|
207
|
+
node ./bin/barista.js liberica employees create -n "测试" --no "9999"
|
|
208
|
+
node ./bin/barista.js liberica employees delete <id> --force
|
|
209
|
+
|
|
210
|
+
# 6. For create with org/position:
|
|
211
|
+
node ./bin/barista.js liberica employees create \
|
|
212
|
+
-n "测试员工" \
|
|
213
|
+
-p "13300000000" \
|
|
214
|
+
-e "test@example.com" \
|
|
215
|
+
-s M \
|
|
216
|
+
--org "销售部" \
|
|
217
|
+
--position "经理" \
|
|
218
|
+
--no "TEST001"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Why This Matters
|
|
222
|
+
|
|
223
|
+
- Unit tests mock the API but don't catch real integration issues
|
|
224
|
+
- BigInteger ID precision only shows with actual API responses
|
|
225
|
+
- Backend may return different error formats than mocks
|
|
226
|
+
- HTTP method issues only appear with real calls
|
|
227
|
+
|
|
228
|
+
### Troubleshooting
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Check current context
|
|
232
|
+
node ./bin/barista.js context show
|
|
233
|
+
|
|
234
|
+
# Re-login if token expired
|
|
235
|
+
node ./bin/barista.js liberica auth login dev shanghai admin@shanghai.newpeaksh.com 123456
|
|
236
|
+
|
|
237
|
+
# Debug: use --json to see full response
|
|
238
|
+
node ./bin/barista.js liberica employees list --json
|
|
239
|
+
|
|
240
|
+
# Debug: check API calls
|
|
241
|
+
# Add to client.ts temporarily:
|
|
242
|
+
console.error('[DEBUG]', JSON.stringify(response.data));
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Testing
|
|
246
|
+
|
|
247
|
+
- Vitest with TypeScript
|
|
248
|
+
- Mock `keytar` and `axios`
|
|
249
|
+
- Tests co-located: `tests/unit/commands/...`
|
|
250
|
+
|
|
251
|
+
## Key Files Reference
|
|
252
|
+
|
|
253
|
+
| Purpose | File |
|
|
254
|
+
|---------|------|
|
|
255
|
+
| API client | `src/core/api/client.ts` |
|
|
256
|
+
| Types | `src/types/employee.ts`, `org.ts`, `position.ts` |
|
|
257
|
+
| Commands | `src/commands/liberica/employees/*.ts` |
|
|
258
|
+
| Integration lessons | `docs/INTEGRATION_NOTES.md` |
|
|
259
|
+
| Command design | `docs/COMMAND_DESIGN_SPEC.md` |
|
|
260
|
+
|
|
261
|
+
## Environment URLs
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
Liberica: https://{tenant}-{env}.newpeaksh.com
|
|
265
|
+
dev: https://{tenant}-dev.newpeaksh.com
|
|
266
|
+
prod-jp: https://{tenant}.newpeakjp.com
|
|
267
|
+
|
|
268
|
+
Arabica: https://arabica-{env}.newpeaksh.com
|
|
269
|
+
prod: https://www.newpeaksh.com
|
|
270
|
+
```
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# Contributing to Barista CLI
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Barista CLI! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Node.js 18+
|
|
10
|
+
- npm 9+
|
|
11
|
+
|
|
12
|
+
### Initial Setup
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Clone the repository
|
|
16
|
+
git clone https://gitlab.newpeaksh.com/coffee/coffee-barista-cli.git
|
|
17
|
+
cd coffee-barista-cli
|
|
18
|
+
|
|
19
|
+
# Install dependencies
|
|
20
|
+
npm install
|
|
21
|
+
|
|
22
|
+
# Link CLI for local development
|
|
23
|
+
npm link
|
|
24
|
+
|
|
25
|
+
# Verify installation
|
|
26
|
+
barista --version
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### VS Code Setup
|
|
30
|
+
|
|
31
|
+
Recommended extensions:
|
|
32
|
+
- ESLint
|
|
33
|
+
- Prettier
|
|
34
|
+
- TypeScript Vue Plugin (Volar)
|
|
35
|
+
|
|
36
|
+
## Development Workflow
|
|
37
|
+
|
|
38
|
+
### ⚠️ IMPORTANT: Design First, Code Later
|
|
39
|
+
|
|
40
|
+
**Before writing ANY code, you MUST complete the design phase.**
|
|
41
|
+
|
|
42
|
+
Skipping design leads to:
|
|
43
|
+
- Wrong API endpoints (like Arabica register using `/api/member/user/register` instead of `/member/user/register`)
|
|
44
|
+
- Missing required parameters
|
|
45
|
+
- Inconsistent command structures
|
|
46
|
+
- Rework and wasted time
|
|
47
|
+
|
|
48
|
+
### 1. Design Phase (MANDATORY)
|
|
49
|
+
|
|
50
|
+
1. Read `docs/COMMAND_DESIGN_SPEC.md`
|
|
51
|
+
2. Find backend Controller:
|
|
52
|
+
```bash
|
|
53
|
+
# Example: Find the register endpoint
|
|
54
|
+
grep -r "register" --include="*.java" ../coffee-arabica-end/facade/
|
|
55
|
+
```
|
|
56
|
+
3. Document the command design:
|
|
57
|
+
- API endpoint and HTTP method
|
|
58
|
+
- All parameters (required vs optional)
|
|
59
|
+
- Request/Response DTOs
|
|
60
|
+
- Error codes and handling
|
|
61
|
+
4. Create design document: `docs/commands/{service}/{resource}/{action}/index.md`
|
|
62
|
+
5. **Get design reviewed** before coding
|
|
63
|
+
|
|
64
|
+
### 2. Create a Branch
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git checkout -b feature/my-feature
|
|
68
|
+
# or
|
|
69
|
+
git checkout -b fix/bug-description
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Implement Changes (After Design Approved)
|
|
73
|
+
|
|
74
|
+
- Write TypeScript code following the approved design
|
|
75
|
+
- Follow existing command patterns
|
|
76
|
+
- Add or update tests
|
|
77
|
+
- Update documentation if needed
|
|
78
|
+
|
|
79
|
+
### 4. Run Tests
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Run all tests
|
|
83
|
+
npm test
|
|
84
|
+
|
|
85
|
+
# Run unit tests only
|
|
86
|
+
npm run test:unit
|
|
87
|
+
|
|
88
|
+
# Run tests in watch mode
|
|
89
|
+
npm test -- --watch
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 5. Lint and Format
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Check code style
|
|
96
|
+
npm run lint
|
|
97
|
+
|
|
98
|
+
# Auto-fix linting issues
|
|
99
|
+
npm run lint -- --fix
|
|
100
|
+
|
|
101
|
+
# Format code with Prettier
|
|
102
|
+
npm run format
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 6. Build
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Build TypeScript
|
|
109
|
+
npm run build
|
|
110
|
+
|
|
111
|
+
# Watch mode for development
|
|
112
|
+
npm run dev
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 7. Commit Changes
|
|
116
|
+
|
|
117
|
+
Follow commit message conventions (see below).
|
|
118
|
+
|
|
119
|
+
### 8. Push and Create PR
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git push origin feature/my-feature
|
|
123
|
+
# Then create PR via GitLab UI
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Code Style
|
|
127
|
+
|
|
128
|
+
We use ESLint and Prettier for code formatting:
|
|
129
|
+
|
|
130
|
+
- **TypeScript**: Strict mode enabled
|
|
131
|
+
- **ESM**: All code uses ES modules with `.js` extensions in imports
|
|
132
|
+
- **Semicolons**: Required
|
|
133
|
+
- **Quotes**: Single quotes for strings
|
|
134
|
+
- **Indentation**: 2 spaces
|
|
135
|
+
|
|
136
|
+
### Import Order
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// 1. Node.js built-ins
|
|
140
|
+
import fs from 'fs';
|
|
141
|
+
import path from 'path';
|
|
142
|
+
|
|
143
|
+
// 2. External packages
|
|
144
|
+
import chalk from 'chalk';
|
|
145
|
+
import { Command } from 'commander';
|
|
146
|
+
|
|
147
|
+
// 3. Internal packages (relative)
|
|
148
|
+
import { configManager } from '../core/config/manager.js';
|
|
149
|
+
import { tokenManager } from '../core/auth/token-manager.js';
|
|
150
|
+
import type { Context, Config } from '../types/index.js';
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Commit Message Conventions
|
|
154
|
+
|
|
155
|
+
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
<type>(<scope>): <subject>
|
|
159
|
+
|
|
160
|
+
[optional body]
|
|
161
|
+
|
|
162
|
+
[optional footer]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Types
|
|
166
|
+
|
|
167
|
+
| Type | Description |
|
|
168
|
+
|------|-------------|
|
|
169
|
+
| feat | New feature |
|
|
170
|
+
| fix | Bug fix |
|
|
171
|
+
| docs | Documentation changes |
|
|
172
|
+
| style | Formatting, missing semicolons, etc. |
|
|
173
|
+
| refactor | Code refactoring |
|
|
174
|
+
| test | Adding tests |
|
|
175
|
+
| chore | Maintenance tasks |
|
|
176
|
+
|
|
177
|
+
### Examples
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Feature
|
|
181
|
+
git commit -m "feat(liberica): add orders cancel command"
|
|
182
|
+
|
|
183
|
+
# Bug fix
|
|
184
|
+
git commit -m "fix(auth): handle token expiration gracefully"
|
|
185
|
+
|
|
186
|
+
# Documentation
|
|
187
|
+
git commit -m "docs: update README with new command examples"
|
|
188
|
+
|
|
189
|
+
# Refactoring
|
|
190
|
+
git commit -m "refactor(config): extract environment validation"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Testing
|
|
194
|
+
|
|
195
|
+
### Test Structure
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
199
|
+
|
|
200
|
+
describe('module name', () => {
|
|
201
|
+
beforeEach(() => {
|
|
202
|
+
vi.clearAllMocks();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should do something specific', () => {
|
|
206
|
+
// Arrange
|
|
207
|
+
const input = 'test';
|
|
208
|
+
|
|
209
|
+
// Act
|
|
210
|
+
const result = functionUnderTest(input);
|
|
211
|
+
|
|
212
|
+
// Assert
|
|
213
|
+
expect(result).toBe('expected');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Running Specific Tests
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Run tests matching a pattern
|
|
222
|
+
npm test -- orders
|
|
223
|
+
|
|
224
|
+
# Run with coverage
|
|
225
|
+
npm test -- --coverage
|
|
226
|
+
|
|
227
|
+
# Run in watch mode for specific file
|
|
228
|
+
npm test -- src/commands/context.test.ts --watch
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Project Structure
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
coffee-barista-cli/
|
|
235
|
+
├── bin/
|
|
236
|
+
│ └── barista # CLI entry point
|
|
237
|
+
├── src/
|
|
238
|
+
│ ├── index.ts # Main entry
|
|
239
|
+
│ ├── commands/ # Command implementations
|
|
240
|
+
│ │ ├── context.ts
|
|
241
|
+
│ │ ├── auth.ts
|
|
242
|
+
│ │ ├── liberica/
|
|
243
|
+
│ │ │ ├── orders.ts
|
|
244
|
+
│ │ │ ├── products.ts
|
|
245
|
+
│ │ │ └── index.ts
|
|
246
|
+
│ │ └── arabica/
|
|
247
|
+
│ │ └── index.ts
|
|
248
|
+
│ ├── core/ # Core functionality
|
|
249
|
+
│ │ ├── config/
|
|
250
|
+
│ │ │ └── manager.ts
|
|
251
|
+
│ │ └── auth/
|
|
252
|
+
│ │ └── token-manager.ts
|
|
253
|
+
│ ├── types/
|
|
254
|
+
│ │ └── index.ts
|
|
255
|
+
│ └── utils/
|
|
256
|
+
├── tests/
|
|
257
|
+
│ ├── unit/ # Unit tests
|
|
258
|
+
│ ├── integration/ # Integration tests
|
|
259
|
+
│ └── fixtures/ # Test fixtures
|
|
260
|
+
├── docs/ # Documentation
|
|
261
|
+
└── package.json
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Documentation
|
|
265
|
+
|
|
266
|
+
When adding new features, update relevant docs:
|
|
267
|
+
|
|
268
|
+
- **New command**:
|
|
269
|
+
1. **必须先**阅读 [命令设计规范](./docs/COMMAND_DESIGN_SPEC.md)
|
|
270
|
+
2. 编写设计文档(按规范模板)
|
|
271
|
+
3. 更新 `docs/COMMANDS.md`
|
|
272
|
+
- **Architecture changes**: Update `docs/ARCHITECTURE.md`
|
|
273
|
+
- **README.md**: Update if CLI interface changes
|
|
274
|
+
|
|
275
|
+
## Pull Request Checklist
|
|
276
|
+
|
|
277
|
+
- [ ] Code follows style guidelines (lint passes)
|
|
278
|
+
- [ ] Tests added/updated and passing
|
|
279
|
+
- [ ] Documentation updated
|
|
280
|
+
- [ ] Commit messages follow conventions
|
|
281
|
+
- [ ] Build succeeds (`npm run build`)
|
|
282
|
+
|
|
283
|
+
## Questions?
|
|
284
|
+
|
|
285
|
+
For questions or discussions:
|
|
286
|
+
- Open an issue in the repository
|
|
287
|
+
- Contact the development team
|
|
288
|
+
|
|
289
|
+
## License
|
|
290
|
+
|
|
291
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|