shawnxixi-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.
Files changed (51) hide show
  1. package/.env.example +2 -0
  2. package/.github/workflows/ci.yml +48 -0
  3. package/AUTH-RESEARCH.md +230 -0
  4. package/CLAUDE.md +102 -0
  5. package/NPM-PUBLISH-RESEARCH.md +163 -0
  6. package/README.md +136 -0
  7. package/dist/commands/biz/calendar.d.ts +12 -0
  8. package/dist/commands/biz/calendar.d.ts.map +1 -0
  9. package/dist/commands/biz/calendar.js +35 -0
  10. package/dist/commands/biz/calendar.js.map +1 -0
  11. package/dist/commands/biz/finance.d.ts +12 -0
  12. package/dist/commands/biz/finance.d.ts.map +1 -0
  13. package/dist/commands/biz/finance.js +34 -0
  14. package/dist/commands/biz/finance.js.map +1 -0
  15. package/dist/commands/biz/item.d.ts +12 -0
  16. package/dist/commands/biz/item.d.ts.map +1 -0
  17. package/dist/commands/biz/item.js +32 -0
  18. package/dist/commands/biz/item.js.map +1 -0
  19. package/dist/commands/biz/record.d.ts +28 -0
  20. package/dist/commands/biz/record.d.ts.map +1 -0
  21. package/dist/commands/biz/record.js +34 -0
  22. package/dist/commands/biz/record.js.map +1 -0
  23. package/dist/commands/biz/todo.d.ts +35 -0
  24. package/dist/commands/biz/todo.d.ts.map +1 -0
  25. package/dist/commands/biz/todo.js +73 -0
  26. package/dist/commands/biz/todo.js.map +1 -0
  27. package/dist/commands/sys/health.d.ts +9 -0
  28. package/dist/commands/sys/health.d.ts.map +1 -0
  29. package/dist/commands/sys/health.js +28 -0
  30. package/dist/commands/sys/health.js.map +1 -0
  31. package/dist/index.d.ts +8 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +199 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/services/api.d.ts +37 -0
  36. package/dist/services/api.d.ts.map +1 -0
  37. package/dist/services/api.js +218 -0
  38. package/dist/services/api.js.map +1 -0
  39. package/jest.config.js +11 -0
  40. package/package.json +40 -0
  41. package/src/commands/biz/calendar.ts +31 -0
  42. package/src/commands/biz/finance.ts +30 -0
  43. package/src/commands/biz/item.ts +28 -0
  44. package/src/commands/biz/record.ts +38 -0
  45. package/src/commands/biz/todo.ts +74 -0
  46. package/src/commands/sys/health.ts +23 -0
  47. package/src/index.ts +209 -0
  48. package/src/services/api.ts +226 -0
  49. package/tests/commands/todo.test.ts +39 -0
  50. package/tests/services/api.test.ts +39 -0
  51. package/tsconfig.json +20 -0
@@ -0,0 +1,37 @@
1
+ /**
2
+ * API Service - HTTP 调用后端
3
+ * 封装与 shawnxixi-server 的通信
4
+ */
5
+ declare class ApiService {
6
+ private client;
7
+ constructor();
8
+ private getToken;
9
+ private refreshToken;
10
+ createTodo(title: string, dueDate?: string, priority?: string): Promise<any>;
11
+ listTodos(status?: string): Promise<any>;
12
+ updateTodo(id: number, updates: Partial<{
13
+ title: string;
14
+ status: string;
15
+ priority: string;
16
+ dueDate: string;
17
+ }>): Promise<any>;
18
+ deleteTodo(id: number): Promise<any>;
19
+ createRecord(title: string, content: string, type?: string, tags?: string): Promise<any>;
20
+ listRecords(type?: string, tags?: string): Promise<any>;
21
+ createFinance(amount: number, type: string, category: string, description?: string): Promise<any>;
22
+ listFinances(type?: string, category?: string): Promise<any>;
23
+ syncHealthData(): Promise<any>;
24
+ queryHealthData(dataType?: string, startDate?: string, endDate?: string): Promise<any>;
25
+ createItem(name: string, category?: string, location?: string, expireDate?: string): Promise<any>;
26
+ listItems(category?: string, status?: string): Promise<any>;
27
+ createCalendarEvent(title: string, startTime: string, endTime: string, description?: string, location?: string): Promise<any>;
28
+ listCalendarEvents(startTime?: string, endTime?: string): Promise<any>;
29
+ createReminder(title: string, triggerTime: string, type?: string): Promise<any>;
30
+ listReminders(status?: string, type?: string): Promise<any>;
31
+ listAuditLogs(entityType?: string, entityId?: number, operation?: string): Promise<any>;
32
+ createTask(title: string, description?: string, priority?: string, source?: string): Promise<any>;
33
+ listTasks(status?: string): Promise<any>;
34
+ }
35
+ export declare const apiService: ApiService;
36
+ export {};
37
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,cAAM,UAAU;IACd,OAAO,CAAC,MAAM,CAAgB;;YAsChB,QAAQ;YAKR,YAAY;IAKpB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAU7D,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM;IAMzB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAK3G,UAAU,CAAC,EAAE,EAAE,MAAM;IAMrB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAgB,EAAE,IAAI,CAAC,EAAE,MAAM;IAUlF,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IASxC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;IAUlF,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAS7C,cAAc;IAKd,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAUvE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAUlF,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAS5C,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAW9G,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IASvD,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,MAAe;IAUxE,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAS5C,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAUxE,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;IAWlF,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM;CAMhC;AAED,eAAO,MAAM,UAAU,YAAmB,CAAC"}
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ /**
3
+ * API Service - HTTP 调用后端
4
+ * 封装与 shawnxixi-server 的通信
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.apiService = void 0;
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const API_BASE = process.env.SHAWNXIXI_API_URL || 'http://localhost:8080';
13
+ class ApiService {
14
+ constructor() {
15
+ this.client = axios_1.default.create({
16
+ baseURL: API_BASE,
17
+ timeout: 10000,
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ },
21
+ });
22
+ // 请求拦截器:添加 auth token
23
+ this.client.interceptors.request.use(async (config) => {
24
+ const token = await this.getToken();
25
+ if (token) {
26
+ config.headers.Authorization = `Bearer ${token}`;
27
+ }
28
+ return config;
29
+ });
30
+ // 响应拦截器:处理 401 刷新 token
31
+ this.client.interceptors.response.use((response) => response, async (error) => {
32
+ if (error.response?.status === 401) {
33
+ // token 过期,尝试刷新
34
+ await this.refreshToken();
35
+ // 重试原请求
36
+ const config = error.config;
37
+ const token = await this.getToken();
38
+ config.headers.Authorization = `Bearer ${token}`;
39
+ return this.client(config);
40
+ }
41
+ return Promise.reject(error);
42
+ });
43
+ }
44
+ async getToken() {
45
+ // TODO: 从 Keychain 读取 token
46
+ return process.env.SHAWNXIXI_API_TOKEN || null;
47
+ }
48
+ async refreshToken() {
49
+ // TODO: 实现 token 刷新逻辑
50
+ }
51
+ // ============ Todo API ============
52
+ async createTodo(title, dueDate, priority) {
53
+ const { data } = await this.client.post('/api/v1/todos', {
54
+ title,
55
+ dueDate,
56
+ priority: priority || 'medium',
57
+ status: 'pending',
58
+ });
59
+ return data;
60
+ }
61
+ async listTodos(status) {
62
+ const params = status ? { status } : {};
63
+ const { data } = await this.client.get('/api/v1/todos', { params });
64
+ return data;
65
+ }
66
+ async updateTodo(id, updates) {
67
+ const { data } = await this.client.put(`/api/v1/todos/${id}`, updates);
68
+ return data;
69
+ }
70
+ async deleteTodo(id) {
71
+ const { data } = await this.client.delete(`/api/v1/todos/${id}`);
72
+ return data;
73
+ }
74
+ // ============ Record API ============
75
+ async createRecord(title, content, type = 'diary', tags) {
76
+ const { data } = await this.client.post('/api/v1/records', {
77
+ title,
78
+ content,
79
+ type,
80
+ tags,
81
+ });
82
+ return data;
83
+ }
84
+ async listRecords(type, tags) {
85
+ const params = {};
86
+ if (type)
87
+ params.type = type;
88
+ if (tags)
89
+ params.tags = tags;
90
+ const { data } = await this.client.get('/api/v1/records', { params });
91
+ return data;
92
+ }
93
+ // ============ Finance API ============
94
+ async createFinance(amount, type, category, description) {
95
+ const { data } = await this.client.post('/api/v1/finances', {
96
+ amount,
97
+ type,
98
+ category,
99
+ description,
100
+ });
101
+ return data;
102
+ }
103
+ async listFinances(type, category) {
104
+ const params = {};
105
+ if (type)
106
+ params.type = type;
107
+ if (category)
108
+ params.category = category;
109
+ const { data } = await this.client.get('/api/v1/finances', { params });
110
+ return data;
111
+ }
112
+ // ============ Health API ============
113
+ async syncHealthData() {
114
+ const { data } = await this.client.post('/api/v1/health-data/sync');
115
+ return data;
116
+ }
117
+ async queryHealthData(dataType, startDate, endDate) {
118
+ const params = {};
119
+ if (dataType)
120
+ params.dataType = dataType;
121
+ if (startDate)
122
+ params.startDate = startDate;
123
+ if (endDate)
124
+ params.endDate = endDate;
125
+ const { data } = await this.client.get('/api/v1/health-data', { params });
126
+ return data;
127
+ }
128
+ // ============ Item API ============
129
+ async createItem(name, category, location, expireDate) {
130
+ const { data } = await this.client.post('/api/v1/items', {
131
+ name,
132
+ category,
133
+ location,
134
+ expireDate,
135
+ });
136
+ return data;
137
+ }
138
+ async listItems(category, status) {
139
+ const params = {};
140
+ if (category)
141
+ params.category = category;
142
+ if (status)
143
+ params.status = status;
144
+ const { data } = await this.client.get('/api/v1/items', { params });
145
+ return data;
146
+ }
147
+ // ============ Calendar API ============
148
+ async createCalendarEvent(title, startTime, endTime, description, location) {
149
+ const { data } = await this.client.post('/api/v1/calendar-events', {
150
+ title,
151
+ startTime,
152
+ endTime,
153
+ description,
154
+ location,
155
+ });
156
+ return data;
157
+ }
158
+ async listCalendarEvents(startTime, endTime) {
159
+ const params = {};
160
+ if (startTime)
161
+ params.startTime = startTime;
162
+ if (endTime)
163
+ params.endTime = endTime;
164
+ const { data } = await this.client.get('/api/v1/calendar-events', { params });
165
+ return data;
166
+ }
167
+ // ============ Reminder API ============
168
+ async createReminder(title, triggerTime, type = 'once') {
169
+ const { data } = await this.client.post('/api/v1/reminders', {
170
+ title,
171
+ triggerTime,
172
+ type,
173
+ status: 'active',
174
+ });
175
+ return data;
176
+ }
177
+ async listReminders(status, type) {
178
+ const params = {};
179
+ if (status)
180
+ params.status = status;
181
+ if (type)
182
+ params.type = type;
183
+ const { data } = await this.client.get('/api/v1/reminders', { params });
184
+ return data;
185
+ }
186
+ // ============ AuditLog API ============
187
+ async listAuditLogs(entityType, entityId, operation) {
188
+ const params = {};
189
+ if (entityType)
190
+ params.entityType = entityType;
191
+ if (entityId)
192
+ params.entityId = String(entityId);
193
+ if (operation)
194
+ params.operation = operation;
195
+ const { data } = await this.client.get('/api/v1/audit-logs', { params });
196
+ return data;
197
+ }
198
+ // ============ Task API ============
199
+ async createTask(title, description, priority, source) {
200
+ const { data } = await this.client.post('/api/v1/tasks', {
201
+ title,
202
+ description,
203
+ priority: priority || 'medium',
204
+ source: source || 'cli',
205
+ status: 'pending',
206
+ });
207
+ return data;
208
+ }
209
+ async listTasks(status) {
210
+ const params = {};
211
+ if (status)
212
+ params.status = status;
213
+ const { data } = await this.client.get('/api/v1/tasks', { params });
214
+ return data;
215
+ }
216
+ }
217
+ exports.apiService = new ApiService();
218
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/services/api.ts"],"names":[],"mappings":"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"}
package/jest.config.js ADDED
@@ -0,0 +1,11 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ roots: ['<rootDir>/tests'],
6
+ testMatch: ['**/*.test.ts'],
7
+ moduleFileExtensions: ['ts', 'js', 'json'],
8
+ collectCoverageFrom: ['src/**/*.ts'],
9
+ coverageDirectory: 'coverage',
10
+ verbose: true,
11
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "shawnxixi-cli",
3
+ "version": "0.1.0",
4
+ "description": "肖嘻 CLI 工具 - OpenClaw 执行肢",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "shawnxixi": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "jest",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/LyuShawn/shawnxixi-cli.git"
17
+ },
18
+ "keywords": [
19
+ "cli",
20
+ "shawnxixi",
21
+ "openclaw"
22
+ ],
23
+ "author": "LyuShawn",
24
+ "license": "ISC",
25
+ "bugs": {
26
+ "url": "https://github.com/LyuShawn/shawnxixi-cli/issues"
27
+ },
28
+ "homepage": "https://github.com/LyuShawn/shawnxixi-cli#readme",
29
+ "devDependencies": {
30
+ "@types/jest": "^29.5.14",
31
+ "@types/node": "^20.11.0",
32
+ "jest": "^29.7.0",
33
+ "ts-jest": "^29.2.0",
34
+ "ts-node": "^10.9.2",
35
+ "typescript": "^5.3.3"
36
+ },
37
+ "dependencies": {
38
+ "axios": "^1.15.0"
39
+ }
40
+ }
@@ -0,0 +1,31 @@
1
+ import { apiService } from '../../services/api';
2
+
3
+ export const calendarCommands = {
4
+ create: async (title: string, options: { start?: string; end?: string; desc?: string } = {}) => {
5
+ if (!options.start || !options.end) {
6
+ console.error('必须指定 --start 和 --end 时间');
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ const result = await (apiService as any).createCalendarEvent
11
+ ? (apiService as any).createCalendarEvent(title, options.start, options.end, options.desc)
12
+ : { error: 'Calendar API not yet implemented in service' };
13
+ console.log(JSON.stringify(result, null, 2));
14
+ } catch (error: any) {
15
+ console.error('创建日程失败:', error.message);
16
+ process.exit(1);
17
+ }
18
+ },
19
+
20
+ list: async (options: { from?: string; to?: string } = {}) => {
21
+ try {
22
+ const result = await (apiService as any).listCalendarEvents
23
+ ? (apiService as any).listCalendarEvents(options)
24
+ : { error: 'Calendar API not yet implemented in service' };
25
+ console.log(JSON.stringify(result, null, 2));
26
+ } catch (error: any) {
27
+ console.error('查询日程失败:', error.message);
28
+ process.exit(1);
29
+ }
30
+ },
31
+ };
@@ -0,0 +1,30 @@
1
+ import { apiService } from '../../services/api';
2
+
3
+ export const financeCommands = {
4
+ create: async (amount: string, options: { type?: string; category?: string; desc?: string } = {}) => {
5
+ const num = parseFloat(amount);
6
+ if (isNaN(num)) {
7
+ console.error('金额必须是数字:', amount);
8
+ process.exit(1);
9
+ }
10
+ const type = options.type || (num >= 0 ? 'income' : 'expense');
11
+ const category = options.category || 'other';
12
+ try {
13
+ const result = await apiService.createFinance(Math.abs(num), type, category, options.desc);
14
+ console.log(JSON.stringify(result, null, 2));
15
+ } catch (error: any) {
16
+ console.error('创建财务记录失败:', error.message);
17
+ process.exit(1);
18
+ }
19
+ },
20
+
21
+ list: async (options: { type?: string; category?: string } = {}) => {
22
+ try {
23
+ const result = await apiService.listFinances(options.type, options.category);
24
+ console.log(JSON.stringify(result, null, 2));
25
+ } catch (error: any) {
26
+ console.error('查询财务记录失败:', error.message);
27
+ process.exit(1);
28
+ }
29
+ },
30
+ };
@@ -0,0 +1,28 @@
1
+ import { apiService } from '../../services/api';
2
+
3
+ export const itemCommands = {
4
+ create: async (name: string, options: { location?: string; expire?: string; category?: string } = {}) => {
5
+ try {
6
+ // Item API is not yet in apiService, use generic approach
7
+ const result = await (apiService as any).createItem
8
+ ? (apiService as any).createItem(name, options)
9
+ : { error: 'Item API not yet implemented in service' };
10
+ console.log(JSON.stringify(result, null, 2));
11
+ } catch (error: any) {
12
+ console.error('创建物品失败:', error.message);
13
+ process.exit(1);
14
+ }
15
+ },
16
+
17
+ list: async (options: { category?: string; expiring?: boolean } = {}) => {
18
+ try {
19
+ const result = await (apiService as any).listItems
20
+ ? (apiService as any).listItems(options)
21
+ : { error: 'Item API not yet implemented in service' };
22
+ console.log(JSON.stringify(result, null, 2));
23
+ } catch (error: any) {
24
+ console.error('查询物品失败:', error.message);
25
+ process.exit(1);
26
+ }
27
+ },
28
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * biz record 命令
3
+ * 记录相关命令:create / list
4
+ */
5
+
6
+ import { apiService } from '../../services/api';
7
+
8
+ export interface RecordItem {
9
+ id: string;
10
+ content: string;
11
+ createdAt: string;
12
+ }
13
+
14
+ export const recordCommands = {
15
+ create: async (title: string, content: string, options: { type?: string; tags?: string } = {}) => {
16
+ try {
17
+ const result = await apiService.createRecord(title, content, options.type, options.tags);
18
+ console.log(JSON.stringify(result, null, 2));
19
+ } catch (error: any) {
20
+ console.error('创建记录失败:', error.message);
21
+ process.exit(1);
22
+ }
23
+ },
24
+
25
+ list: async (options: { type?: string; tags?: string } = {}) => {
26
+ try {
27
+ const result = await apiService.listRecords(options.type, options.tags);
28
+ console.log(JSON.stringify(result, null, 2));
29
+ } catch (error: any) {
30
+ console.error('查询记录失败:', error.message);
31
+ process.exit(1);
32
+ }
33
+ },
34
+ };
35
+
36
+ // 兼容旧导出
37
+ export const createRecord = recordCommands.create;
38
+ export const listRecords = recordCommands.list;
@@ -0,0 +1,74 @@
1
+ /**
2
+ * biz todo 命令
3
+ * 待办相关命令:create / list
4
+ */
5
+
6
+ import { apiService } from '../../services/api';
7
+
8
+ export interface TodoItem {
9
+ id: string;
10
+ title: string;
11
+ completed: boolean;
12
+ createdAt: string;
13
+ }
14
+
15
+ export const todoCommands = {
16
+ create: async (title: string, options: { due?: string; priority?: string } = {}) => {
17
+ try {
18
+ const result = await apiService.createTodo(title, options.due, options.priority);
19
+ console.log(JSON.stringify(result, null, 2));
20
+ } catch (error: any) {
21
+ console.error('创建待办失败:', error.message);
22
+ process.exit(1);
23
+ }
24
+ },
25
+
26
+ list: async (options: { status?: string } = {}) => {
27
+ try {
28
+ const result = await apiService.listTodos(options.status);
29
+ console.log(JSON.stringify(result, null, 2));
30
+ } catch (error: any) {
31
+ console.error('查询待办失败:', error.message);
32
+ process.exit(1);
33
+ }
34
+ },
35
+
36
+ update: async (id: number, options: { title?: string; status?: string; priority?: string; due?: string } = {}) => {
37
+ try {
38
+ const updates: Partial<{title: string; status: string; priority: string; dueDate: string}> = {};
39
+ if (options.title) updates.title = options.title;
40
+ if (options.status) updates.status = options.status;
41
+ if (options.priority) updates.priority = options.priority;
42
+ if (options.due) updates.dueDate = options.due;
43
+ const result = await apiService.updateTodo(id, updates);
44
+ console.log(JSON.stringify(result, null, 2));
45
+ } catch (error: any) {
46
+ console.error('更新待办失败:', error.message);
47
+ process.exit(1);
48
+ }
49
+ },
50
+
51
+ done: async (id: number) => {
52
+ try {
53
+ const result = await apiService.updateTodo(id, { status: 'done' });
54
+ console.log(JSON.stringify(result, null, 2));
55
+ } catch (error: any) {
56
+ console.error('标记待办完成失败:', error.message);
57
+ process.exit(1);
58
+ }
59
+ },
60
+
61
+ delete: async (id: number) => {
62
+ try {
63
+ const result = await apiService.deleteTodo(id);
64
+ console.log(JSON.stringify(result, null, 2));
65
+ } catch (error: any) {
66
+ console.error('删除待办失败:', error.message);
67
+ process.exit(1);
68
+ }
69
+ },
70
+ };
71
+
72
+ // 兼容旧导出
73
+ export const createTodo = todoCommands.create;
74
+ export const listTodos = todoCommands.list;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * sys health 命令
3
+ * 健康数据命令:sync / query
4
+ */
5
+
6
+ import { apiService } from '../../services/api';
7
+
8
+ export const syncHealth = async (dataType?: string, options: { startDate?: string; endDate?: string } = {}) => {
9
+ try {
10
+ if (dataType || options.startDate || options.endDate) {
11
+ // 查询模式
12
+ const result = await apiService.queryHealthData(dataType, options.startDate, options.endDate);
13
+ console.log(JSON.stringify(result, null, 2));
14
+ } else {
15
+ // 同步模式
16
+ const result = await apiService.syncHealthData();
17
+ console.log(JSON.stringify(result, null, 2));
18
+ }
19
+ } catch (error: any) {
20
+ console.error('健康数据操作失败:', error.message);
21
+ process.exit(1);
22
+ }
23
+ };