@vectorx/xhs-cloud-cli 0.6.0 → 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,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"functionsRoot": "./src",
|
|
3
|
+
"functions": [
|
|
4
|
+
{
|
|
5
|
+
"name": "userProfile",
|
|
6
|
+
"directory": "./user",
|
|
7
|
+
"source": "index.js",
|
|
8
|
+
"triggerPath": "/user/profile"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "jsonUsersList",
|
|
12
|
+
"directory": "./json",
|
|
13
|
+
"source": "index.js",
|
|
14
|
+
"triggerPath": "/json/users"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "jsonUsersCreate",
|
|
18
|
+
"directory": "./json",
|
|
19
|
+
"source": "index.js",
|
|
20
|
+
"triggerPath": "/json/users/create"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "jsonUsersBatch",
|
|
24
|
+
"directory": "./json",
|
|
25
|
+
"source": "index.js",
|
|
26
|
+
"triggerPath": "/json/users/batch"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "formSubmit",
|
|
30
|
+
"directory": "./form",
|
|
31
|
+
"source": "index.js",
|
|
32
|
+
"triggerPath": "/form/submit"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "formSubmissions",
|
|
36
|
+
"directory": "./form",
|
|
37
|
+
"source": "index.js",
|
|
38
|
+
"triggerPath": "/form/submissions"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "multipartUpload",
|
|
42
|
+
"directory": "./multipart",
|
|
43
|
+
"source": "index.js",
|
|
44
|
+
"triggerPath": "/multipart/upload"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "multipartFiles",
|
|
48
|
+
"directory": "./multipart",
|
|
49
|
+
"source": "index.js",
|
|
50
|
+
"triggerPath": "/multipart/files"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "binaryUpload",
|
|
54
|
+
"directory": "./binary",
|
|
55
|
+
"source": "index.js",
|
|
56
|
+
"triggerPath": "/binary/upload"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "binaryFiles",
|
|
60
|
+
"directory": "./binary",
|
|
61
|
+
"source": "index.js",
|
|
62
|
+
"triggerPath": "/binary/files"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "textSubmit",
|
|
66
|
+
"directory": "./text",
|
|
67
|
+
"source": "index.js",
|
|
68
|
+
"triggerPath": "/text/submit"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "textLogs",
|
|
72
|
+
"directory": "./text",
|
|
73
|
+
"source": "index.js",
|
|
74
|
+
"triggerPath": "/text/logs"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "textHtml",
|
|
78
|
+
"directory": "./text",
|
|
79
|
+
"source": "index.js",
|
|
80
|
+
"triggerPath": "/text/html"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 二进制数据处理示例函数
|
|
3
|
+
*
|
|
4
|
+
* 覆盖场景:
|
|
5
|
+
* - Content-Type: application/octet-stream
|
|
6
|
+
*
|
|
7
|
+
* 业务场景:处理二进制文件(图片、文档等),模拟保存到数据库或 OSS
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Mock 二进制文件存储记录
|
|
11
|
+
const BINARY_FILES = [];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* POST 请求:上传二进制文件
|
|
15
|
+
*
|
|
16
|
+
* 示例:
|
|
17
|
+
* - POST /binary/upload
|
|
18
|
+
* - Content-Type: application/octet-stream
|
|
19
|
+
* - Body: 二进制数据(Buffer)
|
|
20
|
+
*/
|
|
21
|
+
exports.binaryUpload = async function binaryUpload(event, context) {
|
|
22
|
+
console.log('[binaryUpload] 函数调用开始', {
|
|
23
|
+
ctxId: context?.ctxId,
|
|
24
|
+
eventID: context?.eventID,
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// 获取二进制数据
|
|
29
|
+
let binaryData;
|
|
30
|
+
let fileName = 'binary_file';
|
|
31
|
+
|
|
32
|
+
const params = event?.params;
|
|
33
|
+
|
|
34
|
+
console.log('=====> binaryUpload params', params);
|
|
35
|
+
|
|
36
|
+
// 对齐抖音云托管:二进制数据从 event.params 中获取(Buffer / base64 string / 包装对象)
|
|
37
|
+
if (Buffer.isBuffer(params)) {
|
|
38
|
+
binaryData = params;
|
|
39
|
+
console.log('[binaryUpload] 数据格式:event.params 是 Buffer');
|
|
40
|
+
} else if (typeof params === 'string') {
|
|
41
|
+
// 可能是 base64 编码的字符串
|
|
42
|
+
binaryData = Buffer.from(params, 'base64');
|
|
43
|
+
console.log('[binaryUpload] 数据格式:event.params 是 base64 字符串');
|
|
44
|
+
} else if (params && Buffer.isBuffer(params.data)) {
|
|
45
|
+
binaryData = params.data;
|
|
46
|
+
fileName = params.fileName || fileName;
|
|
47
|
+
console.log('[binaryUpload] 数据格式:event.params.data 是 Buffer');
|
|
48
|
+
} else {
|
|
49
|
+
console.log('[binaryUpload] 错误:无法解析二进制数据格式');
|
|
50
|
+
return {
|
|
51
|
+
ok: false,
|
|
52
|
+
code: 400,
|
|
53
|
+
message: "INVALID_BINARY_DATA",
|
|
54
|
+
detail: "无法解析二进制数据",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!binaryData || binaryData.length === 0) {
|
|
59
|
+
console.log('[binaryUpload] 错误:二进制数据为空');
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
code: 400,
|
|
63
|
+
message: "EMPTY_BINARY_DATA",
|
|
64
|
+
detail: "二进制数据为空",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const fileSize = binaryData.length;
|
|
69
|
+
|
|
70
|
+
console.log('[binaryUpload] 二进制数据信息', {
|
|
71
|
+
size: fileSize,
|
|
72
|
+
fileName,
|
|
73
|
+
header: Array.from(binaryData.slice(0, 4)).map(b => '0x' + b.toString(16).padStart(2, '0')),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// 模拟检测文件类型(通过文件头)
|
|
77
|
+
let detectedType = 'application/octet-stream';
|
|
78
|
+
const header = binaryData.slice(0, 4);
|
|
79
|
+
|
|
80
|
+
// 简单的文件类型检测
|
|
81
|
+
if (header[0] === 0xFF && header[1] === 0xD8) {
|
|
82
|
+
detectedType = 'image/jpeg';
|
|
83
|
+
fileName = fileName.endsWith('.jpg') || fileName.endsWith('.jpeg') ? fileName : fileName + '.jpg';
|
|
84
|
+
console.log('[binaryUpload] 检测到文件类型:JPEG');
|
|
85
|
+
} else if (header[0] === 0x89 && header[1] === 0x50 && header[2] === 0x4E && header[3] === 0x47) {
|
|
86
|
+
detectedType = 'image/png';
|
|
87
|
+
fileName = fileName.endsWith('.png') ? fileName : fileName + '.png';
|
|
88
|
+
console.log('[binaryUpload] 检测到文件类型:PNG');
|
|
89
|
+
} else if (header[0] === 0x25 && header[1] === 0x50 && header[2] === 0x44 && header[3] === 0x46) {
|
|
90
|
+
detectedType = 'application/pdf';
|
|
91
|
+
fileName = fileName.endsWith('.pdf') ? fileName : fileName + '.pdf';
|
|
92
|
+
console.log('[binaryUpload] 检测到文件类型:PDF');
|
|
93
|
+
} else {
|
|
94
|
+
console.log('[binaryUpload] 未识别的文件类型,使用默认类型:application/octet-stream');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 模拟保存到 OSS
|
|
98
|
+
const fileId = `bin_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
99
|
+
const ossUrl = `https://oss.example.com/binary/${fileId}`;
|
|
100
|
+
|
|
101
|
+
console.log('[binaryUpload] 生成文件 ID 和 OSS URL', { fileId, ossUrl });
|
|
102
|
+
|
|
103
|
+
// 模拟数据库保存文件元数据
|
|
104
|
+
const fileRecord = {
|
|
105
|
+
id: fileId,
|
|
106
|
+
fileName,
|
|
107
|
+
fileType: detectedType,
|
|
108
|
+
fileSize,
|
|
109
|
+
ossUrl,
|
|
110
|
+
uploadedAt: new Date().toISOString(),
|
|
111
|
+
// 实际场景中,二进制数据会保存到 OSS,这里只保存元数据
|
|
112
|
+
// binaryData: binaryData.toString('base64'), // 仅用于测试,实际不存储
|
|
113
|
+
};
|
|
114
|
+
BINARY_FILES.push(fileRecord);
|
|
115
|
+
|
|
116
|
+
console.log('[binaryUpload] 二进制文件上传成功', {
|
|
117
|
+
fileId,
|
|
118
|
+
fileName,
|
|
119
|
+
fileType: detectedType,
|
|
120
|
+
fileSize,
|
|
121
|
+
ossUrl,
|
|
122
|
+
totalFiles: BINARY_FILES.length,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
ok: true,
|
|
127
|
+
code: 0,
|
|
128
|
+
message: "BINARY_UPLOAD_OK",
|
|
129
|
+
data: {
|
|
130
|
+
fileId,
|
|
131
|
+
fileName,
|
|
132
|
+
fileType: detectedType,
|
|
133
|
+
fileSize,
|
|
134
|
+
ossUrl,
|
|
135
|
+
uploadedAt: fileRecord.uploadedAt,
|
|
136
|
+
},
|
|
137
|
+
contentType: "application/octet-stream",
|
|
138
|
+
// 模拟业务逻辑:返回处理结果
|
|
139
|
+
businessLogic: {
|
|
140
|
+
detectedType,
|
|
141
|
+
savedToDatabase: true,
|
|
142
|
+
uploadedToOSS: true,
|
|
143
|
+
canAccess: true,
|
|
144
|
+
// 模拟文件处理:如果是图片,可以生成缩略图等
|
|
145
|
+
processed: detectedType.startsWith('image/') ? {
|
|
146
|
+
thumbnailGenerated: true,
|
|
147
|
+
thumbnailUrl: `${ossUrl}_thumb`,
|
|
148
|
+
} : null,
|
|
149
|
+
},
|
|
150
|
+
meta: {
|
|
151
|
+
ctxId: context.ctxId,
|
|
152
|
+
eventID: context.eventID,
|
|
153
|
+
eventType: context.eventType,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* GET 请求:查询二进制文件信息
|
|
160
|
+
*
|
|
161
|
+
* 示例:
|
|
162
|
+
* - GET /binary/files?fileType=image/jpeg
|
|
163
|
+
*/
|
|
164
|
+
exports.binaryFiles = async function binaryFiles(event, context) {
|
|
165
|
+
console.log('[binaryFiles] 函数调用开始', {
|
|
166
|
+
ctxId: context?.ctxId,
|
|
167
|
+
eventID: context?.eventID,
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const { fileType } = context.query;
|
|
172
|
+
|
|
173
|
+
console.log('[binaryFiles] 查询参数', { fileType, totalFiles: BINARY_FILES.length });
|
|
174
|
+
|
|
175
|
+
let files = BINARY_FILES;
|
|
176
|
+
|
|
177
|
+
// 模拟数据库查询:按文件类型过滤
|
|
178
|
+
if (fileType) {
|
|
179
|
+
files = BINARY_FILES.filter(f => f.fileType === fileType);
|
|
180
|
+
console.log('[binaryFiles] 按文件类型过滤', { fileType, filteredCount: files.length });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
console.log('[binaryFiles] 查询结果', { total: files.length });
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
ok: true,
|
|
187
|
+
code: 0,
|
|
188
|
+
message: "BINARY_FILES_OK",
|
|
189
|
+
data: {
|
|
190
|
+
total: files.length,
|
|
191
|
+
files: files.map(f => ({
|
|
192
|
+
id: f.id,
|
|
193
|
+
fileName: f.fileName,
|
|
194
|
+
fileType: f.fileType,
|
|
195
|
+
fileSize: f.fileSize,
|
|
196
|
+
ossUrl: f.ossUrl,
|
|
197
|
+
uploadedAt: f.uploadedAt,
|
|
198
|
+
})),
|
|
199
|
+
},
|
|
200
|
+
contentType: "application/octet-stream",
|
|
201
|
+
meta: {
|
|
202
|
+
ctxId: context.ctxId,
|
|
203
|
+
eventID: context.eventID,
|
|
204
|
+
eventType: context.eventType,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* context 能力验证 - 业务逻辑层(与 handler 拆分)
|
|
3
|
+
* 目标:尽量覆盖 headers/httpMethod/path/url/query/cookies/trigger 以及 set/remove/status/setCookie/clearCookie。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
function pick(obj, keys) {
|
|
7
|
+
const out = {};
|
|
8
|
+
for (const k of keys) out[k] = obj?.[k];
|
|
9
|
+
return out;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
exports.buildEcho = function buildEcho(context) {
|
|
13
|
+
const summary = {
|
|
14
|
+
httpMethod: context.httpMethod,
|
|
15
|
+
path: context.path,
|
|
16
|
+
url: context.url,
|
|
17
|
+
query: context.query,
|
|
18
|
+
cookies: context.cookies,
|
|
19
|
+
trigger: context.trigger,
|
|
20
|
+
// 只回传少量 header,避免噪音/敏感信息
|
|
21
|
+
headers: pick(context.headers, ["content-type", "user-agent", "xhs-cloud-trigger", "cookie"]),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
ok: true,
|
|
26
|
+
code: 0,
|
|
27
|
+
message: "CTX_ECHO_OK",
|
|
28
|
+
data: summary,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.applyHeaderOps = function applyHeaderOps(context) {
|
|
33
|
+
// set/remove 都需要能影响最终 response headers
|
|
34
|
+
context.set("x-ctx-keep", "1");
|
|
35
|
+
context.set("x-ctx-drop", "1");
|
|
36
|
+
context.remove("x-ctx-drop");
|
|
37
|
+
|
|
38
|
+
context.status(500)
|
|
39
|
+
return {
|
|
40
|
+
ok: true,
|
|
41
|
+
code: 0,
|
|
42
|
+
message: "CTX_HEADERS_OK",
|
|
43
|
+
data: {
|
|
44
|
+
note: "请检查响应头:应存在 x-ctx-keep,不应存在 x-ctx-drop",
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
exports.applyStatusOps = function applyStatusOps(context, statusCode) {
|
|
50
|
+
context.status(statusCode);
|
|
51
|
+
context.set("x-ctx-status", String(statusCode));
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
ok: true,
|
|
55
|
+
code: 0,
|
|
56
|
+
message: "CTX_STATUS_OK",
|
|
57
|
+
data: { statusCode },
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
exports.applyCookieSet = function applyCookieSet(context, name, value) {
|
|
62
|
+
context.setCookie(name, value, {
|
|
63
|
+
httpOnly: true,
|
|
64
|
+
sameSite: "lax",
|
|
65
|
+
path: "/",
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
ok: true,
|
|
70
|
+
code: 0,
|
|
71
|
+
message: "CTX_COOKIE_SET_OK",
|
|
72
|
+
data: {
|
|
73
|
+
name,
|
|
74
|
+
value,
|
|
75
|
+
note: "请检查响应头 Set-Cookie 是否存在",
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
exports.applyCookieClear = function applyCookieClear(context, name) {
|
|
81
|
+
context.clearCookie(name, { path: "/" });
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
ok: true,
|
|
85
|
+
code: 0,
|
|
86
|
+
message: "CTX_COOKIE_CLEAR_OK",
|
|
87
|
+
data: {
|
|
88
|
+
name,
|
|
89
|
+
note: "请检查响应头 Set-Cookie 是否把 cookie 过期清理",
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* context 能力验证 - handler 层
|
|
3
|
+
* 注意:新增函数数量控制在 <= 5 个
|
|
4
|
+
*
|
|
5
|
+
* 路由见 agent-cloudbase-functions.json:
|
|
6
|
+
* - GET /ctx/echo
|
|
7
|
+
* - GET /ctx/headers
|
|
8
|
+
* - GET /ctx/status
|
|
9
|
+
* - GET /ctx/cookie/set
|
|
10
|
+
* - GET /ctx/cookie/clear
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
buildEcho,
|
|
15
|
+
applyHeaderOps,
|
|
16
|
+
applyStatusOps,
|
|
17
|
+
applyCookieSet,
|
|
18
|
+
applyCookieClear,
|
|
19
|
+
} = require("./context-service");
|
|
20
|
+
|
|
21
|
+
// 1) 验证基础字段是否齐全(headers/httpMethod/path/url/query/cookies/trigger)
|
|
22
|
+
exports.ctxEcho = async function ctxEcho(event, context) {
|
|
23
|
+
return buildEcho(context);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// 2) 验证 context.set / context.remove
|
|
27
|
+
exports.ctxHeaders = async function ctxHeaders(event, context) {
|
|
28
|
+
return applyHeaderOps(context);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 3) 验证 context.status
|
|
32
|
+
exports.ctxStatus = async function ctxStatus(event, context) {
|
|
33
|
+
const query = context.query || {};
|
|
34
|
+
const raw = query.code ?? "201";
|
|
35
|
+
// 12312321 throw new Error('Invalid statdxus code: ' + raw);
|
|
36
|
+
const code = Number(raw);
|
|
37
|
+
const statusCode = Number.isFinite(code) ? code : 201;
|
|
38
|
+
return applyStatusOps(context, statusCode);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// 4) 验证 context.setCookie
|
|
42
|
+
exports.ctxCookieSet = async function ctxCookieSet(event, context) {
|
|
43
|
+
const query = context.query || {};
|
|
44
|
+
console.log('====>', JSON.stringify(event, null, 2), event.params, context.query)
|
|
45
|
+
const name = query.name || "token";
|
|
46
|
+
const value = query.value || `v_${Date.now()}`;
|
|
47
|
+
return applyCookieSet(context, String(name), String(value));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// 5) 验证 context.clearCookie
|
|
51
|
+
exports.ctxCookieClear = async function ctxCookieClear(event, context) {
|
|
52
|
+
const query = context.query || {};
|
|
53
|
+
const name = query.name || "token";
|
|
54
|
+
return applyCookieClear(context, String(name));
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
|