Skip to content
This repository was archived by the owner on May 6, 2025. It is now read-only.

Commit 86a4902

Browse files
committed
add storage proxy and upgrade cloud api request
1 parent f843265 commit 86a4902

56 files changed

Lines changed: 1410 additions & 217 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55
"prettier",
66
"prettier/@typescript-eslint"
77
],
8-
"plugins": [
9-
"@typescript-eslint"
10-
],
8+
"plugins": ["@typescript-eslint"],
119
"rules": {
1210
"no-console": "off",
1311
"no-unused-vars": "error",
14-
"semi": [
15-
"error",
16-
"never"
17-
],
12+
"semi": ["error", "never"],
1813
"quotes": [
1914
"error",
2015
"single",
@@ -24,7 +19,8 @@
2419
],
2520
"@typescript-eslint/explicit-member-accessibility": "off",
2621
"@typescript-eslint/explicit-function-return-type": "off",
27-
"@typescript-eslint/interface-name-prefix": "off"
22+
"@typescript-eslint/interface-name-prefix": "off",
23+
"@typescript-eslint/no-explicit-any": "off"
2824
},
2925
"env": {
3026
"es6": true,
@@ -40,4 +36,4 @@
4036
}
4137
}
4238
]
43-
}
39+
}

.prettierrc.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
module.exports = {
2+
// 一行最多 100 字符
3+
printWidth: 100,
4+
// 使用 4 个空格缩进
25
tabWidth: 4,
6+
// 不使用缩进符,而使用空格
7+
useTabs: false,
8+
// 行尾无分号
39
semi: false,
4-
singleQuote: true
10+
// 使用单引号
11+
singleQuote: true,
12+
// 对象的 key 仅在必要时用引号
13+
quoteProps: 'as-needed',
14+
// 末尾不需要逗号
15+
trailingComma: 'none',
16+
// 大括号内的首尾需要空格
17+
bracketSpacing: true,
18+
// 每个文件格式化的范围是文件的全部内容
19+
rangeStart: 0,
20+
rangeEnd: Infinity,
21+
// 不需要写文件开头的 @prettier
22+
requirePragma: false,
23+
// 不需要自动在文件开头插入 @prettier
24+
insertPragma: false,
25+
// 使用默认的折行标准
26+
proseWrap: 'preserve',
27+
// 换行符使用 lf
28+
endOfLine: 'lf'
529
}

bin/cloudbase.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const updateNotifier = require('update-notifier')
88
const address = require('address')
99
const pkg = require('../package.json')
1010

11+
let processArgv = process.argv
1112
const isBeta = pkg.version.indexOf('-') > -1
1213

1314
const userNodeVersion = Number(
@@ -52,6 +53,25 @@ notifier.notify({
5253
isGlobal: true
5354
})
5455

56+
// 测试模式
57+
if (processArgv.includes('--deb')) {
58+
console.log(
59+
chalk.bold.yellow('====\n您已经进入 debug 模式!\n移除 --deb 选项退出 debug 模式!\n====')
60+
)
61+
}
62+
63+
// debug 模式
64+
process.IS_DEBUG = processArgv.includes('--deb')
65+
66+
// 需要隐藏的选项
67+
const hideArgs = ['--deb']
68+
hideArgs.forEach(arg => {
69+
const index = processArgv.indexOf(arg)
70+
if (index > -1) {
71+
processArgv.splice(index, 1)
72+
}
73+
})
74+
5575
// 注册命令
5676
require('../lib')
5777

@@ -71,11 +91,7 @@ Sentry.configureScope(scope => {
7191
})
7292

7393
// 设置 options 选项
74-
program.option(
75-
'--config-file <path>',
76-
'设置配置文件,默认为 ./cloudbaserc.js 或 .cloudbaserc.json'
77-
)
78-
program.option('--debug', 'open debug mode')
94+
program.option('--config-file <path>', '设置配置文件,默认为 ./cloudbaserc.js 或 .cloudbaserc.json')
7995

8096
program.version(pkg.version, '-V, --version', '输出当前 CloudBase CLI 版本')
8197

@@ -109,9 +125,7 @@ if (process.argv.length < 3) {
109125
program.outputHelp()
110126
}
111127

112-
program.parse(process.argv)
113-
114-
process.IS_DEBUG = program.debug
128+
program.parse(processArgv)
115129

116130
function errorHandler(err) {
117131
const stackIngoreErrors = ['TencentCloudSDKHttpException', 'CloudBaseError']

lib/commands/functions/debug.js

Lines changed: 134 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,142 @@
11
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
211
var __importDefault = (this && this.__importDefault) || function (mod) {
312
return (mod && mod.__esModule) ? mod : { "default": mod };
413
};
514
Object.defineProperty(exports, "__esModule", { value: true });
615
const path_1 = __importDefault(require("path"));
716
const child_process_1 = require("child_process");
8-
const bootstrapFilePath = path_1.default.join(__dirname, '../../utils/runtime/nodejs/bootstrap.js');
9-
child_process_1.execFile('node', [bootstrapFilePath], {
10-
cwd: path_1.default.dirname(bootstrapFilePath),
11-
maxBuffer: 1024 * 1024,
12-
timeout: 20,
13-
env: Object.assign(Object.assign({}, process.env), { SCF_FUNCTION_HANDLER: 'index:main', SCF_FUNCTION_NAME: 'main', GLOBAL_USER_FILE_PATH: '/Users/hengechang/Desktop/cloudbase-demo/functions/test/' })
14-
}, (error, stdout, stderr) => {
15-
if (error) {
16-
console.log(error);
17+
const error_1 = require("../../error");
18+
const utils_1 = require("../../utils");
19+
const bootstrapFilePath = path_1.default.join(__dirname, '../../../runtime/nodejs/bootstrap.js');
20+
function checkJSON(data) {
21+
try {
22+
JSON.parse(data);
23+
}
24+
catch (e) {
25+
throw new error_1.CloudBaseError('非法的 JSON 字符串');
1726
}
18-
console.log(stdout);
19-
console.log(stderr);
20-
});
27+
}
28+
function getDebugArgs(port = 9229) {
29+
return [
30+
`--inspect-brk=0.0.0.0:${port}`,
31+
'--nolazy',
32+
'--expose-gc',
33+
'--max-semi-space-size=150',
34+
'--max-old-space-size=2707'
35+
];
36+
}
37+
function spawnNodeProcess(args, options) {
38+
const commonOptions = {
39+
cwd: path_1.default.dirname(bootstrapFilePath),
40+
windowsHide: true
41+
};
42+
const exec = child_process_1.spawn('node', args, Object.assign(Object.assign({}, commonOptions), options));
43+
exec.on('error', e => {
44+
console.log(`进程执行异常:${e.message}`);
45+
setTimeout(() => { }, 100);
46+
});
47+
exec.stdout.on('data', data => {
48+
console.log(`${data}`);
49+
});
50+
exec.stderr.on('data', data => {
51+
console.log(`${data}`);
52+
});
53+
exec.on('close', code => {
54+
if (code !== 0) {
55+
console.log(`\n云函数执行异常退出,错误码:${code}`);
56+
}
57+
});
58+
}
59+
function debugFunctionByPath(functionPath, options) {
60+
return __awaiter(this, void 0, void 0, function* () {
61+
const { params, debug, port } = options;
62+
params && checkJSON(params);
63+
const filePath = path_1.default.resolve(functionPath);
64+
utils_1.checkPathExist(filePath, true);
65+
let debugDirname;
66+
if (utils_1.isDirectory(filePath)) {
67+
const exists = utils_1.checkPathExist(path_1.default.join(filePath, 'index.js'));
68+
if (!exists) {
69+
throw new error_1.CloudBaseError('index.js 文件不存在!');
70+
}
71+
debugDirname = filePath;
72+
}
73+
else {
74+
const { base, dir } = path_1.default.parse(filePath);
75+
if (base !== 'index.js') {
76+
throw new error_1.CloudBaseError('index.js 文件不存在!');
77+
}
78+
debugDirname = dir;
79+
}
80+
try {
81+
const fileExports = require(path_1.default.join(debugDirname, 'index.js'));
82+
if (!fileExports.main) {
83+
throw new error_1.CloudBaseError('main 方法不存在!');
84+
}
85+
}
86+
catch (e) {
87+
throw new error_1.CloudBaseError(`导入云函数异常:${e.message}`);
88+
}
89+
const debugArgs = getDebugArgs(port);
90+
const args = debug ? [...debugArgs, bootstrapFilePath] : [bootstrapFilePath];
91+
console.log('> 以默认配置启动 Node 云函数调试');
92+
spawnNodeProcess(args, {
93+
env: Object.assign(Object.assign({}, process.env), { SCF_FUNCTION_HANDLER: 'index.main', SCF_FUNCTION_NAME: 'main', GLOBAL_USER_FILE_PATH: path_1.default.join(debugDirname, path_1.default.sep), SCF_EVENT_BODY: params || '{}' })
94+
});
95+
});
96+
}
97+
exports.debugFunctionByPath = debugFunctionByPath;
98+
function debugByConfig(ctx, options) {
99+
return __awaiter(this, void 0, void 0, function* () {
100+
const { name, config } = ctx;
101+
const { params, debug, port } = options;
102+
params && checkJSON(params);
103+
let functionPath = path_1.default.resolve(config.functionRoot, name);
104+
const filePath = path_1.default.resolve(functionPath);
105+
utils_1.checkPathExist(filePath, true);
106+
let debugDirname;
107+
const funcConfig = utils_1.findAndFlattenFunConfig(config, name);
108+
const handlers = (funcConfig.handler || 'index.js').split('.');
109+
const indexFileName = handlers[0];
110+
const indexFile = `${indexFileName}.js`;
111+
const mainFunction = handlers[1];
112+
if (utils_1.isDirectory(filePath)) {
113+
const exists = utils_1.checkPathExist(path_1.default.join(filePath, indexFile));
114+
if (!exists) {
115+
throw new error_1.CloudBaseError(`${indexFile} 文件不存在!`);
116+
}
117+
debugDirname = filePath;
118+
}
119+
else {
120+
const { base, dir } = path_1.default.parse(filePath);
121+
if (base !== indexFile) {
122+
throw new error_1.CloudBaseError(`${indexFile} 文件不存在!`);
123+
}
124+
debugDirname = dir;
125+
}
126+
try {
127+
const fileExports = require(path_1.default.join(debugDirname, indexFile));
128+
if (!fileExports[mainFunction]) {
129+
throw new error_1.CloudBaseError(`handler 中的 ${mainFunction} 方法不存在,请检查你的配置!`);
130+
}
131+
}
132+
catch (e) {
133+
throw new error_1.CloudBaseError(`导入云函数异常:${e.message}`);
134+
}
135+
const debugArgs = getDebugArgs(port);
136+
const args = debug ? [...debugArgs, bootstrapFilePath] : [bootstrapFilePath];
137+
spawnNodeProcess(args, {
138+
env: Object.assign(Object.assign(Object.assign({}, process.env), { SCF_FUNCTION_HANDLER: funcConfig.handler || 'index.main', SCF_FUNCTION_NAME: funcConfig.name || 'main', GLOBAL_USER_FILE_PATH: path_1.default.join(debugDirname, path_1.default.sep), SCF_EVENT_BODY: params || JSON.stringify(funcConfig.params || {}) }), funcConfig.envVariables)
139+
});
140+
});
141+
}
142+
exports.debugByConfig = debugByConfig;

lib/commands/functions/index.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const trigger_delete_1 = require("./trigger-delete");
2727
const invoke_1 = require("./invoke");
2828
const copy_1 = require("./copy");
2929
const code_download_1 = require("./code-download");
30+
const debug_1 = require("./debug");
3031
function getFunctionContext(name, envId, configPath) {
3132
return __awaiter(this, void 0, void 0, function* () {
3233
const cloudBaseConfig = yield utils_1.resolveCloudBaseConfig(configPath);
@@ -232,6 +233,44 @@ const commands = [
232233
const ctx = yield getFunctionContext(functionName, envId, configFile);
233234
yield trigger_delete_1.triggerDelete(ctx, triggerName);
234235
})
236+
},
237+
{
238+
cmd: 'functions:invoke:local',
239+
options: [
240+
{
241+
flags: '--path <path>',
242+
desc: '云函数路径,使用默认配置直接调用云函数,无需配置文件'
243+
},
244+
{
245+
flags: '--name <name>',
246+
desc: '指定云函数的名称进行调用,需要配置文件'
247+
},
248+
{
249+
flags: '--params <params>',
250+
desc: '调用函数传入的参数,JSON 字符串格式'
251+
},
252+
{
253+
flags: '--port <port>',
254+
desc: '启动调试时监听的端口号,默认为 9229'
255+
},
256+
{
257+
flags: '--debug',
258+
desc: '启动调试模式'
259+
}
260+
],
261+
desc: '本地运行云函数',
262+
handler: (options) => __awaiter(void 0, void 0, void 0, function* () {
263+
const { path } = options;
264+
if (path) {
265+
yield debug_1.debugFunctionByPath(path, options);
266+
}
267+
else {
268+
const { name } = options;
269+
const { configFile } = options.parent;
270+
const ctx = yield getFunctionContext(name, '', configFile);
271+
yield debug_1.debugByConfig(ctx, options);
272+
}
273+
})
235274
}
236275
];
237276
commands.forEach(item => {

0 commit comments

Comments
 (0)