@vectorx/xhs-cloud-cli 0.6.1 → 1.0.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/bin/rcb.js +47 -157
- package/lib/commands/agent/dev.js +3 -0
- package/lib/commands/auth/login.js +13 -0
- package/lib/commands/env/create.js +156 -0
- package/lib/commands/env/index.js +20 -0
- package/lib/commands/env/info.js +106 -0
- package/lib/commands/env/list.js +93 -0
- package/lib/commands/env/set.js +129 -0
- package/lib/commands/fun/deploy.js +182 -0
- package/lib/commands/fun/dev.js +183 -0
- package/lib/commands/fun/index.js +20 -0
- package/lib/commands/fun/list.js +77 -0
- package/lib/commands/fun/new.js +125 -0
- package/lib/commands/index.js +2 -0
- package/lib/constants/cmd.js +9 -9
- package/lib/core/base.js +75 -1
- package/lib/decorators/auth.js +6 -0
- package/lib/decorators/captureError.js +1 -0
- package/lib/main.js +6 -0
- package/package.json +7 -6
- package/templates/ai-cloud-functions-example/.env.template +1 -0
- package/templates/ai-cloud-functions-example/README.md +277 -0
- package/templates/ai-cloud-functions-example/agent-cloudbase-functions.json +83 -0
- package/templates/ai-cloud-functions-example/package.json +10 -0
- package/templates/ai-cloud-functions-example/src/binary/index.js +207 -0
- package/templates/ai-cloud-functions-example/src/context/context-service.js +94 -0
- package/templates/ai-cloud-functions-example/src/context/index.js +57 -0
- package/templates/ai-cloud-functions-example/src/env/index.js +264 -0
- package/templates/ai-cloud-functions-example/src/form/index.js +138 -0
- package/templates/ai-cloud-functions-example/src/index.js +0 -0
- package/templates/ai-cloud-functions-example/src/json/index.js +194 -0
- package/templates/ai-cloud-functions-example/src/multipart/index.js +189 -0
- package/templates/ai-cloud-functions-example/src/text/index.js +319 -0
- package/templates/ai-cloud-functions-example/src/user/index.js +82 -0
- package/templates/chatbox-agent/project.config.json +2 -2
- package/templates/cloudfunction-template/.env.template +2 -0
- package/templates/cloudfunction-template/agent-cloudbase-functions.json +17 -0
- package/templates/cloudfunction-template/package.json +11 -0
- package/templates/cloudfunction-template/project.config.json +5 -0
- package/templates/cloudfunction-template/src/echo.js +27 -0
- package/templates/cloudfunction-template/src/index.js +34 -0
- package/types/commands/env/create.d.ts +19 -0
- package/types/commands/env/index.d.ts +4 -0
- package/types/commands/env/info.d.ts +14 -0
- package/types/commands/env/list.d.ts +11 -0
- package/types/commands/env/set.d.ts +14 -0
- package/types/commands/fun/deploy.d.ts +14 -0
- package/types/commands/fun/dev.d.ts +14 -0
- package/types/commands/fun/index.d.ts +4 -0
- package/types/commands/fun/list.d.ts +14 -0
- package/types/commands/fun/new.d.ts +16 -0
- package/types/commands/index.d.ts +2 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 环境变量测试示例函数
|
|
3
|
+
*
|
|
4
|
+
* 功能:
|
|
5
|
+
* - 读取并返回所有环境变量(或指定的环境变量)
|
|
6
|
+
* - 测试从服务设置面板传入的环境变量是否生效
|
|
7
|
+
* - 演示如何在云函数中使用环境变量
|
|
8
|
+
*
|
|
9
|
+
* 使用场景:
|
|
10
|
+
* - 验证环境变量配置是否正确
|
|
11
|
+
* - 调试环境变量相关问题
|
|
12
|
+
* - 测试环境变量的注入机制
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* GET 请求:获取所有环境变量(过滤敏感信息)
|
|
17
|
+
*
|
|
18
|
+
* 示例:
|
|
19
|
+
* - GET /env/vars
|
|
20
|
+
* - GET /env/vars?keys=API_KEY,DATABASE_URL
|
|
21
|
+
*/
|
|
22
|
+
exports.envVars = async function envVars(event, context) {
|
|
23
|
+
console.log('[envVars] 函数调用开始', {
|
|
24
|
+
ctxId: context?.ctxId,
|
|
25
|
+
eventID: context?.eventID,
|
|
26
|
+
timestamp: new Date().toISOString(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const query = (event && event.params) || {};
|
|
30
|
+
const keysParam = query.keys; // 可选:指定要返回的环境变量键,用逗号分隔
|
|
31
|
+
|
|
32
|
+
// 如果指定了 keys 参数,只返回指定的环境变量
|
|
33
|
+
if (keysParam && typeof keysParam === 'string') {
|
|
34
|
+
const requestedKeys = keysParam.split(',').map(k => k.trim()).filter(k => k);
|
|
35
|
+
const filteredEnv = {};
|
|
36
|
+
|
|
37
|
+
requestedKeys.forEach(key => {
|
|
38
|
+
if (process.env[key] !== undefined) {
|
|
39
|
+
filteredEnv[key] = process.env[key];
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log('[envVars] 返回指定的环境变量', {
|
|
44
|
+
requested: requestedKeys.length,
|
|
45
|
+
found: Object.keys(filteredEnv).length,
|
|
46
|
+
keys: Object.keys(filteredEnv),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
ok: true,
|
|
51
|
+
code: 0,
|
|
52
|
+
message: "ENV_VARS_FILTERED_OK",
|
|
53
|
+
data: {
|
|
54
|
+
envVars: filteredEnv,
|
|
55
|
+
requested: requestedKeys,
|
|
56
|
+
found: Object.keys(filteredEnv),
|
|
57
|
+
missing: requestedKeys.filter(k => !(k in filteredEnv)),
|
|
58
|
+
},
|
|
59
|
+
contentType: "application/json",
|
|
60
|
+
meta: {
|
|
61
|
+
ctxId: context.ctxId,
|
|
62
|
+
eventID: context.eventID,
|
|
63
|
+
eventType: context.eventType,
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 返回所有环境变量(过滤掉一些敏感或系统相关的变量)
|
|
69
|
+
const allEnvVars = {};
|
|
70
|
+
const sensitiveKeys = ['PATH', 'NODE_PATH', 'HOME', 'USER', 'SHELL', 'PWD', 'LANG', 'LC_'];
|
|
71
|
+
const systemKeys = ['npm_', 'NPM_', 'NODE_', '_'];
|
|
72
|
+
|
|
73
|
+
Object.keys(process.env).forEach(key => {
|
|
74
|
+
// 过滤掉敏感和系统相关的环境变量
|
|
75
|
+
const isSensitive = sensitiveKeys.some(sk => key.includes(sk));
|
|
76
|
+
const isSystem = systemKeys.some(sk => key.startsWith(sk));
|
|
77
|
+
|
|
78
|
+
if (!isSensitive && !isSystem) {
|
|
79
|
+
allEnvVars[key] = process.env[key];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
console.log('[envVars] 返回所有环境变量', {
|
|
84
|
+
total: Object.keys(process.env).length,
|
|
85
|
+
returned: Object.keys(allEnvVars).length,
|
|
86
|
+
keys: Object.keys(allEnvVars),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
ok: true,
|
|
91
|
+
code: 0,
|
|
92
|
+
message: "ENV_VARS_ALL_OK",
|
|
93
|
+
data: {
|
|
94
|
+
envVars: allEnvVars,
|
|
95
|
+
total: Object.keys(process.env).length,
|
|
96
|
+
returned: Object.keys(allEnvVars).length,
|
|
97
|
+
note: "已过滤敏感和系统相关的环境变量",
|
|
98
|
+
},
|
|
99
|
+
contentType: "application/json",
|
|
100
|
+
meta: {
|
|
101
|
+
ctxId: context.ctxId,
|
|
102
|
+
eventID: context.eventID,
|
|
103
|
+
eventType: context.eventType,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* POST 请求:测试环境变量的使用
|
|
110
|
+
*
|
|
111
|
+
* 功能:
|
|
112
|
+
* - 读取指定的环境变量并返回
|
|
113
|
+
* - 演示如何在业务逻辑中使用环境变量
|
|
114
|
+
*
|
|
115
|
+
* 示例:
|
|
116
|
+
* - POST /env/test
|
|
117
|
+
* - Body: { "keys": ["API_KEY", "DATABASE_URL", "test-one", "test-two"] }
|
|
118
|
+
*/
|
|
119
|
+
exports.envTest = async function envTest(event, context) {
|
|
120
|
+
console.log('[envTest] 函数调用开始', {
|
|
121
|
+
ctxId: context?.ctxId,
|
|
122
|
+
eventID: context?.eventID,
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const body = (event && event.params) || {};
|
|
127
|
+
const { keys } = body;
|
|
128
|
+
|
|
129
|
+
if (!Array.isArray(keys) || keys.length === 0) {
|
|
130
|
+
console.log('[envTest] 参数验证失败:keys 必须是非空数组');
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
code: 400,
|
|
134
|
+
message: "INVALID_KEYS",
|
|
135
|
+
detail: "keys 必须是非空数组",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 读取指定的环境变量
|
|
140
|
+
const results = {};
|
|
141
|
+
const missing = [];
|
|
142
|
+
|
|
143
|
+
keys.forEach(key => {
|
|
144
|
+
const value = process.env[key];
|
|
145
|
+
if (value !== undefined) {
|
|
146
|
+
results[key] = value;
|
|
147
|
+
console.log(`[envTest] 找到环境变量: ${key} = ${value}`);
|
|
148
|
+
} else {
|
|
149
|
+
missing.push(key);
|
|
150
|
+
console.log(`[envTest] 环境变量不存在: ${key}`);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 模拟使用环境变量的业务逻辑
|
|
155
|
+
const mockBusinessLogic = () => {
|
|
156
|
+
// 示例:使用 API_KEY 环境变量
|
|
157
|
+
const apiKey = process.env['API_KEY'] || process.env['api_key'];
|
|
158
|
+
if (apiKey) {
|
|
159
|
+
console.log('[envTest] 使用 API_KEY 进行业务逻辑处理');
|
|
160
|
+
// 这里可以调用外部 API 等操作
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// 示例:使用数据库连接字符串
|
|
164
|
+
const dbUrl = process.env['DATABASE_URL'] || process.env['database_url'];
|
|
165
|
+
if (dbUrl) {
|
|
166
|
+
console.log('[envTest] 使用 DATABASE_URL 连接数据库');
|
|
167
|
+
// 这里可以连接数据库等操作
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
apiKeyConfigured: !!apiKey,
|
|
172
|
+
databaseConfigured: !!dbUrl,
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const businessStatus = mockBusinessLogic();
|
|
177
|
+
|
|
178
|
+
console.log('[envTest] 测试结果', {
|
|
179
|
+
requested: keys.length,
|
|
180
|
+
found: Object.keys(results).length,
|
|
181
|
+
missing: missing.length,
|
|
182
|
+
businessStatus,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
ok: true,
|
|
187
|
+
code: 0,
|
|
188
|
+
message: "ENV_TEST_OK",
|
|
189
|
+
data: {
|
|
190
|
+
requested: keys,
|
|
191
|
+
found: results,
|
|
192
|
+
missing: missing,
|
|
193
|
+
businessStatus,
|
|
194
|
+
summary: {
|
|
195
|
+
total: keys.length,
|
|
196
|
+
found: Object.keys(results).length,
|
|
197
|
+
missing: missing.length,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
contentType: "application/json",
|
|
201
|
+
meta: {
|
|
202
|
+
ctxId: context.ctxId,
|
|
203
|
+
eventID: context.eventID,
|
|
204
|
+
eventType: context.eventType,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* GET 请求:检查特定环境变量是否存在
|
|
211
|
+
*
|
|
212
|
+
* 示例:
|
|
213
|
+
* - GET /env/check?key=API_KEY
|
|
214
|
+
* - GET /env/check?key=test-one
|
|
215
|
+
*/
|
|
216
|
+
exports.envCheck = async function envCheck(event, context) {
|
|
217
|
+
console.log('[envCheck] 函数调用开始', {
|
|
218
|
+
ctxId: context?.ctxId,
|
|
219
|
+
eventID: context?.eventID,
|
|
220
|
+
timestamp: new Date().toISOString(),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log('process', process.env);
|
|
224
|
+
|
|
225
|
+
const query = (event && event.params) || {};
|
|
226
|
+
const key = query.key;
|
|
227
|
+
|
|
228
|
+
if (!key || typeof key !== 'string') {
|
|
229
|
+
console.log('[envCheck] 参数验证失败:key 是必填参数');
|
|
230
|
+
return {
|
|
231
|
+
ok: false,
|
|
232
|
+
code: 400,
|
|
233
|
+
message: "MISSING_KEY",
|
|
234
|
+
detail: "key 是必填参数",
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const value = process.env[key];
|
|
239
|
+
const exists = value !== undefined;
|
|
240
|
+
|
|
241
|
+
console.log('[envCheck] 检查结果', {
|
|
242
|
+
key,
|
|
243
|
+
exists,
|
|
244
|
+
hasValue: exists && value.length > 0,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
ok: true,
|
|
249
|
+
code: 0,
|
|
250
|
+
message: exists ? "ENV_KEY_EXISTS" : "ENV_KEY_NOT_FOUND",
|
|
251
|
+
data: {
|
|
252
|
+
key,
|
|
253
|
+
exists,
|
|
254
|
+
value: exists ? value : null,
|
|
255
|
+
hasValue: exists && value && value.length > 0,
|
|
256
|
+
},
|
|
257
|
+
contentType: "application/json",
|
|
258
|
+
meta: {
|
|
259
|
+
ctxId: context.ctxId,
|
|
260
|
+
eventID: context.eventID,
|
|
261
|
+
eventType: context.eventType,
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表单提交处理示例函数
|
|
3
|
+
*
|
|
4
|
+
* 覆盖场景:
|
|
5
|
+
* - Content-Type: application/x-www-form-urlencoded
|
|
6
|
+
*
|
|
7
|
+
* 业务场景:表单数据提交和处理(模拟表单提交到数据库)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Mock 表单提交记录
|
|
11
|
+
const FORM_SUBMISSIONS = [];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* POST 请求:提交表单数据
|
|
15
|
+
*
|
|
16
|
+
* 示例:
|
|
17
|
+
* - POST /form/submit
|
|
18
|
+
* - Content-Type: application/x-www-form-urlencoded
|
|
19
|
+
* - Body: name=张三&email=zhangsan@example.com&message=这是一条留言
|
|
20
|
+
*/
|
|
21
|
+
exports.formSubmit = async function formSubmit(event, context) {
|
|
22
|
+
console.log('[formSubmit] 函数调用开始', {
|
|
23
|
+
ctxId: context?.ctxId,
|
|
24
|
+
eventID: context?.eventID,
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
console.log('=====>', event);
|
|
29
|
+
// 处理表单数据:可能是 URLSearchParams 字符串或已解析的对象
|
|
30
|
+
let formData = {};
|
|
31
|
+
|
|
32
|
+
const params = event?.params;
|
|
33
|
+
|
|
34
|
+
if (typeof params === 'string') {
|
|
35
|
+
// 如果是字符串,解析 URLSearchParams
|
|
36
|
+
const qs = new URLSearchParams(params);
|
|
37
|
+
for (const [key, value] of qs.entries()) {
|
|
38
|
+
formData[key] = value;
|
|
39
|
+
}
|
|
40
|
+
console.log('[formSubmit] 解析 URLSearchParams 字符串');
|
|
41
|
+
} else if (params && typeof params === 'object') {
|
|
42
|
+
// 如果已经是对象,直接使用
|
|
43
|
+
formData = params;
|
|
44
|
+
console.log('[formSubmit] 使用已解析的对象数据');
|
|
45
|
+
} else {
|
|
46
|
+
formData = {};
|
|
47
|
+
console.log('[formSubmit] 使用 event 作为表单数据');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { name, email, message, phone } = formData;
|
|
51
|
+
|
|
52
|
+
console.log('[formSubmit] 表单数据', { name, email, hasMessage: !!message, hasPhone: !!phone });
|
|
53
|
+
|
|
54
|
+
if (!name || !email) {
|
|
55
|
+
console.log('[formSubmit] 参数验证失败:缺少必填字段');
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
code: 400,
|
|
59
|
+
message: "MISSING_REQUIRED_FIELDS",
|
|
60
|
+
detail: "name 和 email 为必填字段",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// 模拟数据库保存
|
|
65
|
+
const submission = {
|
|
66
|
+
id: `sub${Date.now()}`,
|
|
67
|
+
name,
|
|
68
|
+
email,
|
|
69
|
+
phone: phone || null,
|
|
70
|
+
message: message || null,
|
|
71
|
+
submittedAt: new Date().toISOString(),
|
|
72
|
+
};
|
|
73
|
+
FORM_SUBMISSIONS.push(submission);
|
|
74
|
+
|
|
75
|
+
console.log('[formSubmit] 表单提交成功', {
|
|
76
|
+
submissionId: submission.id,
|
|
77
|
+
email: submission.email,
|
|
78
|
+
totalSubmissions: FORM_SUBMISSIONS.length,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
ok: true,
|
|
83
|
+
code: 0,
|
|
84
|
+
message: "FORM_SUBMIT_OK",
|
|
85
|
+
data: submission,
|
|
86
|
+
contentType: "application/x-www-form-urlencoded",
|
|
87
|
+
meta: {
|
|
88
|
+
ctxId: context.ctxId,
|
|
89
|
+
eventID: context.eventID,
|
|
90
|
+
eventType: context.eventType,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* GET 请求:查询表单提交记录
|
|
97
|
+
*
|
|
98
|
+
* 示例:
|
|
99
|
+
* - GET /form/submissions?email=zhangsan@example.com
|
|
100
|
+
*/
|
|
101
|
+
exports.formSubmissions = async function formSubmissions(event, context) {
|
|
102
|
+
console.log('[formSubmissions] 函数调用开始', {
|
|
103
|
+
ctxId: context?.ctxId,
|
|
104
|
+
eventID: context?.eventID,
|
|
105
|
+
timestamp: new Date().toISOString(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const query = (event && event.params) || {};
|
|
109
|
+
const { email } = query;
|
|
110
|
+
|
|
111
|
+
console.log('[formSubmissions] 查询参数', { email, totalRecords: FORM_SUBMISSIONS.length });
|
|
112
|
+
|
|
113
|
+
let submissions = FORM_SUBMISSIONS;
|
|
114
|
+
|
|
115
|
+
// 模拟数据库查询:按邮箱过滤
|
|
116
|
+
if (email) {
|
|
117
|
+
submissions = FORM_SUBMISSIONS.filter(s => s.email === email);
|
|
118
|
+
console.log('[formSubmissions] 按邮箱过滤', { email, filteredCount: submissions.length });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.log('[formSubmissions] 查询结果', { total: submissions.length });
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
ok: true,
|
|
125
|
+
code: 0,
|
|
126
|
+
message: "FORM_QUERY_OK",
|
|
127
|
+
data: {
|
|
128
|
+
total: submissions.length,
|
|
129
|
+
submissions,
|
|
130
|
+
},
|
|
131
|
+
contentType: "application/x-www-form-urlencoded",
|
|
132
|
+
meta: {
|
|
133
|
+
ctxId: context.ctxId,
|
|
134
|
+
eventID: context.eventID,
|
|
135
|
+
eventType: context.eventType,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON 请求处理示例函数
|
|
3
|
+
*
|
|
4
|
+
* 覆盖场景:
|
|
5
|
+
* - Content-Type: application/json
|
|
6
|
+
* - Content-Type: application/vnd.api+json (带 +json 后缀)
|
|
7
|
+
*
|
|
8
|
+
* 业务场景:用户数据查询和创建(模拟数据库操作)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Mock 数据库数据
|
|
12
|
+
const MOCK_DB = [
|
|
13
|
+
{ id: "u001", name: "张三", email: "zhangsan@example.com", age: 25 },
|
|
14
|
+
{ id: "u002", name: "李四", email: "lisi@example.com", age: 30 },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* GET 请求:查询用户列表(通过 query 参数)
|
|
19
|
+
*
|
|
20
|
+
* 示例:
|
|
21
|
+
* - GET /json/users?page=1&limit=10
|
|
22
|
+
*/
|
|
23
|
+
exports.jsonUsersList = async function jsonUsersList(event, context) {
|
|
24
|
+
console.log('[jsonUsersList] 函数调用开始', {
|
|
25
|
+
ctxId: context?.ctxId,
|
|
26
|
+
eventID: context?.eventID,
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const query = (event && event.params) || {};
|
|
31
|
+
const page = parseInt(query.page) || 1;
|
|
32
|
+
const limit = parseInt(query.limit) || 10;
|
|
33
|
+
|
|
34
|
+
console.log('[jsonUsersList] 查询参数', { page, limit, query });
|
|
35
|
+
|
|
36
|
+
const start = (page - 1) * limit;
|
|
37
|
+
const end = start + limit;
|
|
38
|
+
const users = MOCK_DB.slice(start, end);
|
|
39
|
+
|
|
40
|
+
console.log('[jsonUsersList] 查询结果', {
|
|
41
|
+
total: MOCK_DB.length,
|
|
42
|
+
returned: users.length,
|
|
43
|
+
page,
|
|
44
|
+
limit,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
ok: true,
|
|
49
|
+
code: 0,
|
|
50
|
+
message: "JSON_GET_USERS_OK",
|
|
51
|
+
data: {
|
|
52
|
+
users,
|
|
53
|
+
pagination: {
|
|
54
|
+
page,
|
|
55
|
+
limit,
|
|
56
|
+
total: MOCK_DB.length,
|
|
57
|
+
totalPages: Math.ceil(MOCK_DB.length / limit),
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
contentType: "application/json",
|
|
61
|
+
meta: {
|
|
62
|
+
ctxId: context.ctxId,
|
|
63
|
+
eventID: context.eventID,
|
|
64
|
+
eventType: context.eventType,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* POST 请求:创建用户(JSON Body)
|
|
71
|
+
*
|
|
72
|
+
* 示例:
|
|
73
|
+
* - POST /json/users/create
|
|
74
|
+
* - Body: { "name": "王五", "email": "wangwu@example.com", "age": 28 }
|
|
75
|
+
*/
|
|
76
|
+
exports.jsonUsersCreate = async function jsonUsersCreate(event, context) {
|
|
77
|
+
console.log('[jsonUsersCreate] 函数调用开始', {
|
|
78
|
+
ctxId: context?.ctxId,
|
|
79
|
+
eventID: context?.eventID,
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const body = (event && event.params) || {};
|
|
84
|
+
const { name, email, age } = body;
|
|
85
|
+
|
|
86
|
+
console.log('[jsonUsersCreate] 请求参数', { name, email, age });
|
|
87
|
+
|
|
88
|
+
if (!name || !email) {
|
|
89
|
+
console.log('[jsonUsersCreate] 参数验证失败:缺少必填字段');
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
code: 400,
|
|
93
|
+
message: "MISSING_REQUIRED_FIELDS",
|
|
94
|
+
detail: "name 和 email 为必填字段",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 模拟数据库查询:检查邮箱是否已存在
|
|
99
|
+
const exists = MOCK_DB.find(u => u.email === email);
|
|
100
|
+
if (exists) {
|
|
101
|
+
console.log('[jsonUsersCreate] 邮箱已存在', { email });
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
code: 409,
|
|
105
|
+
message: "EMAIL_EXISTS",
|
|
106
|
+
detail: `邮箱 ${email} 已被使用`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 模拟数据库插入
|
|
111
|
+
const newUser = {
|
|
112
|
+
id: `u${String(MOCK_DB.length + 1).padStart(3, '0')}`,
|
|
113
|
+
name,
|
|
114
|
+
email,
|
|
115
|
+
age: age || null,
|
|
116
|
+
};
|
|
117
|
+
MOCK_DB.push(newUser);
|
|
118
|
+
|
|
119
|
+
console.log('[jsonUsersCreate] 用户创建成功', {
|
|
120
|
+
userId: newUser.id,
|
|
121
|
+
email: newUser.email,
|
|
122
|
+
totalUsers: MOCK_DB.length,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
ok: true,
|
|
127
|
+
code: 0,
|
|
128
|
+
message: "JSON_POST_CREATE_OK",
|
|
129
|
+
data: newUser,
|
|
130
|
+
contentType: "application/json",
|
|
131
|
+
meta: {
|
|
132
|
+
ctxId: context.ctxId,
|
|
133
|
+
eventID: context.eventID,
|
|
134
|
+
eventType: context.eventType,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* POST 请求:批量查询用户(JSON Body with +json content-type)
|
|
141
|
+
*
|
|
142
|
+
* 示例:
|
|
143
|
+
* - POST /json/users/batch
|
|
144
|
+
* - Content-Type: application/vnd.api+json
|
|
145
|
+
* - Body: { "userIds": ["u001", "u002"] }
|
|
146
|
+
*/
|
|
147
|
+
exports.jsonUsersBatch = async function jsonUsersBatch(event, context) {
|
|
148
|
+
console.log('[jsonUsersBatch] 函数调用开始', {
|
|
149
|
+
ctxId: context?.ctxId,
|
|
150
|
+
eventID: context?.eventID,
|
|
151
|
+
timestamp: new Date().toISOString(),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const body = (event && event.params) || {};
|
|
155
|
+
const { userIds } = body;
|
|
156
|
+
|
|
157
|
+
console.log('[jsonUsersBatch] 批量查询请求', { userIds, count: userIds?.length });
|
|
158
|
+
|
|
159
|
+
if (!Array.isArray(userIds) || userIds.length === 0) {
|
|
160
|
+
console.log('[jsonUsersBatch] 参数验证失败:userIds 必须是非空数组');
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
code: 400,
|
|
164
|
+
message: "INVALID_USER_IDS",
|
|
165
|
+
detail: "userIds 必须是非空数组",
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 模拟数据库批量查询
|
|
170
|
+
const users = MOCK_DB.filter(u => userIds.includes(u.id));
|
|
171
|
+
|
|
172
|
+
console.log('[jsonUsersBatch] 批量查询结果', {
|
|
173
|
+
requested: userIds.length,
|
|
174
|
+
found: users.length,
|
|
175
|
+
userIds: users.map(u => u.id),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
ok: true,
|
|
180
|
+
code: 0,
|
|
181
|
+
message: "JSON_BATCH_QUERY_OK",
|
|
182
|
+
data: {
|
|
183
|
+
requested: userIds.length,
|
|
184
|
+
found: users.length,
|
|
185
|
+
users,
|
|
186
|
+
},
|
|
187
|
+
contentType: "application/vnd.api+json",
|
|
188
|
+
meta: {
|
|
189
|
+
ctxId: context.ctxId,
|
|
190
|
+
eventID: context.eventID,
|
|
191
|
+
eventType: context.eventType,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
};
|