@cloudbase/cli 2.12.3-beta.4 → 2.12.4-beta.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/dist/standalone/cli.js +1510 -186
- package/package.json +1 -1
package/dist/standalone/cli.js
CHANGED
|
@@ -326169,7 +326169,7 @@ module.exports = function generate_pattern(it, $keyword, $ruleType) {
|
|
|
326169
326169
|
/***/ ((module) => {
|
|
326170
326170
|
|
|
326171
326171
|
"use strict";
|
|
326172
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@cloudbase/cli","version":"2.12.
|
|
326172
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@cloudbase/cli","version":"2.12.4-beta.0","description":"cli tool for cloudbase","main":"lib/index.js","scripts":{"build":"rimraf lib types && tsc --resolveJsonModule && cpx \\"src/**/*.html\\" lib","watch":"rimraf lib types && tsc -w","dev":"rimraf lib types && cpx \\"src/**/*.html\\" lib && tsc -w","eslint":"eslint \\"./**/*.ts\\"","test":"node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand --forceExit --detectOpenHandles --coverage --verbose --testTimeout=10000","tsc":"tsc","pkg":"pkg ./bin/cloudbase.js --out-path ./pkg","postinstall":"node ./post-install.js || exit 0 && patch-package","prepublishOnly":"node ./scripts/check-publish-source.js","debug":"bin/tcb.js lowcode watch","build:bundle":"webpack --config build/webpack/cli.cjs && webpack --config build/webpack/ccr.cjs && node build/scripts/copy-figlet-fonts.js","package:darwin-arm64":"OS=darwin ARCH=arm64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:darwin-x64":"OS=darwin ARCH=x64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:linux-arm64":"OS=linux ARCH=arm64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:linux-x64":"OS=linux ARCH=x64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:all":"bash build/scripts/build-all.sh","node:fetch:one":"node -e \\"require(\'child_process\').execSync(\'bash build/scripts/fetch-node.sh\',{stdio:\'inherit\'})\\"","node:fetch:all":"NODE_VERSION=22.18.0 bash build/scripts/fetch-node.sh --all","node:fetch:win-x64":"OS=windows ARCH=x64 NODE_VERSION=22.18.0 bash build/scripts/fetch-node.sh","node:fetch:win-arm64":"OS=windows ARCH=arm64 NODE_VERSION=22.18.0 bash build/scripts/fetch-node.sh","package:windows-x64":"OS=windows ARCH=x64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:windows-arm64":"OS=windows ARCH=arm64 VERSION= node -e \\"require(\'child_process\').execSync(\'bash build/scripts/package.sh\',{stdio:\'inherit\'})\\"","package:windows-all":"npm run -s node:fetch:win-x64 && npm run -s node:fetch:win-arm64 && npm run -s package:windows-x64 && npm run -s package:windows-arm64","package:npm":"npm run build && npm run build:bundle && bash build/scripts/prepare-publish.sh","out:prune":"bash build/scripts/prune-out.sh","i18n:scan":"i18next-scanner --config locales/i18next-scanner.config.js && node locales/scripts/generate.js","i18n:sync":"node locales/scripts/sync.js sync","publish":"node ./scripts/publish.js"},"repository":{"type":"git","url":"https://github.com/TencentCloudBase/cloud-base-cli.git"},"bin":{"cloudbase":"bin/cloudbase.js","cloudbase-mcp":"bin/cloudbase-mcp.cjs","tcb":"bin/tcb.js"},"husky":{"hooks":{"pre-commit":"npm run build"}},"author":"cwuyiqing@gmail.com","license":"ISC","dependencies":{"@cloudbase/cloud-api":"^0.5.5","@cloudbase/cloudbase-mcp":"^2.7.3","@cloudbase/framework-core":"^1.9.7","@cloudbase/functions-framework":"1.16.0","@cloudbase/iac-core":"0.0.3-alpha.14","@cloudbase/lowcode-cli":"^0.23.0","@cloudbase/manager-node":"4.7.4","@cloudbase/toolbox":"0.7.16","@dotenvx/dotenvx":"^1.48.3","@musistudio/claude-code-router":"1.0.36","address":"^1.1.2","camelcase-keys":"^7.0.2","chalk":"^2.4.2","cli-table3":"^0.5.1","commander":"7","del":"^5.1.0","didyoumean":"^1.2.2","enquirer":"^2.3.6","execa":"^4.0.3","figlet":"^1.7.0","fs-extra":"^8.1.0","gradient-string":"^2.0.2","https-proxy-agent":"^5.0.1","i":"^0.3.7","inquirer":"^6.5.0","json-schema-to-typescript":"^14.0.5","lodash":"^4.17.21","log-symbols":"^3.0.0","lowdb":"^1.0.0","make-dir":"^3.0.0","node-fetch":"^2.6.0","nodemon":"^3.1.4","npm":"^11.5.2","open":"^7.0.0","ora":"^4.0.2","os-locale":"5.0.0","patch-package":"^8.0.0","portfinder":"^1.0.28","progress":"^2.0.3","query-string":"^6.8.1","reflect-metadata":"^0.1.13","semver":"^7.3.7","simple-git":"^3.28.0","tar-fs":"^2.0.1","terminal-link":"^2.1.1","toml":"^3.0.0","unzipper":"^0.10.10","update-notifier":"^4.0.0","xdg-basedir":"^4.0.0","yargs":"^16.2.0","yargs-parser":"^21.0.1","zod":"^4.0.13"},"devDependencies":{"@babel/parser":"^7.28.4","@babel/traverse":"^7.28.4","@babel/types":"^7.28.4","@types/fs-extra":"^11.0.4","@types/jest":"^27","@types/koa__router":"^8.0.11","@types/lodash":"^4.14.182","@types/node":"^12.12.38","@types/node-fetch":"^2.5.4","@types/react":"^17.0.37","@types/semver":"^7.3.9","@types/unzipper":"^0.10.11","@types/webpack-dev-server":"^3.11.1","@typescript-eslint/eslint-plugin":"^4.8.1","@typescript-eslint/parser":"^4.8.1","cpx":"^1.5.0","eslint":"^7.14.0","eslint-config-alloy":"^3.8.2","husky":"^3.0.9","i18next-scanner":"^4.6.0","jest":"^27","rimraf":"^3.0.2","ts-jest":"^27","typescript":"^4.7.2","webpack":"^5.92.0","webpack-cli":"^5.1.4"},"packageManager":"yarn@3.6.2+sha512.2c2f8b9615e6659773f65cdec7cf92ef773a98a99e611579601f61c7a91ec94c89c929aac86f1cee819421a9b0db7acfd53ec3ebb95af44f77f77634b08b9557","ai":{"skills":"./skills","skillsIndex":"./skills/index.json","compatible":["codebuddy","cursor","copilot","claude","windsurf"],"description":"CloudBase CLI - 腾讯云云开发命令行工具,支持云函数、云数据库、静态托管等全栈云开发能力"}}');
|
|
326173
326173
|
|
|
326174
326174
|
/***/ }),
|
|
326175
326175
|
|
|
@@ -410366,8 +410366,6 @@ function openUrl(url) {
|
|
|
410366
410366
|
const child = yield (0, open_1.default)(url, { url: true });
|
|
410367
410367
|
if (child === null || child === void 0 ? void 0 : child.once) {
|
|
410368
410368
|
child.once('error', (error) => __awaiter(this, void 0, void 0, function* () {
|
|
410369
|
-
const code = (error === null || error === void 0 ? void 0 : error.code) || 'UNKNOWN';
|
|
410370
|
-
console.warn(`自动打开浏览器失败(${code})。`);
|
|
410371
410369
|
if (shouldUseBrowserEnvFallback()) {
|
|
410372
410370
|
yield openUrlByBrowserEnv(url);
|
|
410373
410371
|
}
|
|
@@ -410394,8 +410392,8 @@ function getDataFromWeb(getUrl, type, options = {}) {
|
|
|
410394
410392
|
throw new error_1.CloudBaseError('callbackTimeout must be a positive number');
|
|
410395
410393
|
}
|
|
410396
410394
|
const url = getUrl(port);
|
|
410397
|
-
console.log('\n\n
|
|
410398
|
-
console.log(`\n${url}`);
|
|
410395
|
+
console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
|
|
410396
|
+
console.log(`\n${url}\n`);
|
|
410399
410397
|
if (!noBrowser) {
|
|
410400
410398
|
// 对 url 转码, 避免 wsl 无法正常打开地址
|
|
410401
410399
|
// https://www.npmjs.com/package/open#url
|
|
@@ -459817,7 +459815,7 @@ let FunctionDetail = class FunctionDetail extends common_1.Command {
|
|
|
459817
459815
|
this.logDetail(data, name);
|
|
459818
459816
|
}
|
|
459819
459817
|
catch (e) {
|
|
459820
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
459818
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
459821
459819
|
throw new error_1.CloudBaseError((0, i18n_1.t)('[{{name}}] 函数不存在', { name }));
|
|
459822
459820
|
}
|
|
459823
459821
|
throw e;
|
|
@@ -467696,12 +467694,15 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467696
467694
|
functionDetail = yield functionService.getFunctionDetail(name, codeSecret);
|
|
467697
467695
|
}
|
|
467698
467696
|
catch (e) {
|
|
467699
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
467697
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
467700
467698
|
throw new error_1.CloudBaseError((0, i18n_1.t)('云函数 [{{name}}] 不存在,请先使用 tcb fn deploy {{name}} 部署函数', { name }));
|
|
467701
467699
|
}
|
|
467702
467700
|
throw e;
|
|
467703
467701
|
}
|
|
467704
467702
|
const cloudFunctionType = (functionDetail === null || functionDetail === void 0 ? void 0 : functionDetail.Type) || 'Event';
|
|
467703
|
+
const cloudInstallDependency = (functionDetail === null || functionDetail === void 0 ? void 0 : functionDetail.InstallDependency) === 'TRUE';
|
|
467704
|
+
const cloudHandler = (functionDetail === null || functionDetail === void 0 ? void 0 : functionDetail.Handler) || 'index.main';
|
|
467705
|
+
const cloudRuntime = (functionDetail === null || functionDetail === void 0 ? void 0 : functionDetail.Runtime) || func.runtime;
|
|
467705
467706
|
if (!func.type) {
|
|
467706
467707
|
func.type = cloudFunctionType;
|
|
467707
467708
|
}
|
|
@@ -467712,6 +467713,16 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467712
467713
|
localType: func.type
|
|
467713
467714
|
}));
|
|
467714
467715
|
}
|
|
467716
|
+
if (func.installDependency === undefined) {
|
|
467717
|
+
func.installDependency = cloudInstallDependency;
|
|
467718
|
+
log.verbose((0, i18n_1.t)('使用云端配置 installDependency: {{value}}', { value: cloudInstallDependency }));
|
|
467719
|
+
}
|
|
467720
|
+
if (!func.handler || func.handler === 'index.main') {
|
|
467721
|
+
func.handler = cloudHandler;
|
|
467722
|
+
}
|
|
467723
|
+
if (!func.runtime) {
|
|
467724
|
+
func.runtime = cloudRuntime;
|
|
467725
|
+
}
|
|
467715
467726
|
if (cloudFunctionType === 'HTTP') {
|
|
467716
467727
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, Object.assign(Object.assign({}, func), { type: 'HTTP', runtime: functionDetail.Runtime }), {
|
|
467717
467728
|
cancelMessage: (0, i18n_1.t)('已取消更新,请手动创建 scf_bootstrap 文件后重试'),
|
|
@@ -467753,7 +467764,7 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467753
467764
|
const mainFile = path_1.default.basename(packageJson.main).replace(/\.[^.]+$/, '');
|
|
467754
467765
|
handler = `${mainFile}.main`;
|
|
467755
467766
|
}
|
|
467756
|
-
return Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { handler });
|
|
467767
|
+
return Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { handler, installDependency: true });
|
|
467757
467768
|
}
|
|
467758
467769
|
catch (e) {
|
|
467759
467770
|
return null;
|
|
@@ -467893,11 +467904,11 @@ let CodeDownload = class CodeDownload extends common_1.Command {
|
|
|
467893
467904
|
yield functionService.getFunctionDetail(name, codeSecret);
|
|
467894
467905
|
}
|
|
467895
467906
|
catch (e) {
|
|
467896
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
467907
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
467897
467908
|
throw new error_1.CloudBaseError((0, i18n_1.t)('云函数 [{{name}}] 不存在!\n\n使用 {{command}} 命令查看已部署云函数', {
|
|
467898
467909
|
name,
|
|
467899
|
-
command: (0, utils_1.highlightCommand)('
|
|
467900
|
-
}));
|
|
467910
|
+
command: (0, utils_1.highlightCommand)('tcb fn list')
|
|
467911
|
+
}), e);
|
|
467901
467912
|
}
|
|
467902
467913
|
return;
|
|
467903
467914
|
}
|
|
@@ -493884,7 +493895,7 @@ function validateFunctionTypeChange(envId, func, log) {
|
|
|
493884
493895
|
existingFunction = yield functionService.getFunctionDetail(func.name);
|
|
493885
493896
|
}
|
|
493886
493897
|
catch (e) {
|
|
493887
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
493898
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
493888
493899
|
log.error((0, i18n_1.t)('云函数 [{{name}}] 不存在,请先部署函数', { name: func.name }));
|
|
493889
493900
|
return false;
|
|
493890
493901
|
}
|
|
@@ -493927,6 +493938,10 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493927
493938
|
{
|
|
493928
493939
|
flags: '-e, --envId <envId>',
|
|
493929
493940
|
desc: (0, i18n_1.t)('环境 Id')
|
|
493941
|
+
},
|
|
493942
|
+
{
|
|
493943
|
+
flags: '--yes',
|
|
493944
|
+
desc: (0, i18n_1.t)('跳过交互确认,使用默认选项自动执行')
|
|
493930
493945
|
}
|
|
493931
493946
|
],
|
|
493932
493947
|
desc: (0, i18n_1.t)('更新云函数配置'),
|
|
@@ -493936,26 +493951,35 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493936
493951
|
}
|
|
493937
493952
|
execute(ctx, params, log) {
|
|
493938
493953
|
return __awaiter(this, void 0, void 0, function* () {
|
|
493939
|
-
let { envId, config: { functions } } = ctx;
|
|
493954
|
+
let { envId, config: { functions }, options } = ctx;
|
|
493940
493955
|
const name = params === null || params === void 0 ? void 0 : params[0];
|
|
493956
|
+
const { yes } = options;
|
|
493941
493957
|
let isBathUpdate = false;
|
|
493942
493958
|
if (!envId) {
|
|
493943
493959
|
envId = yield (0, utils_1.selectEnv)({ envTypes: [constant_1.EnvType.BAAS, constant_1.EnvType.WEDA] });
|
|
493944
493960
|
}
|
|
493945
493961
|
if (!name) {
|
|
493946
|
-
|
|
493947
|
-
|
|
493948
|
-
|
|
493949
|
-
|
|
493950
|
-
|
|
493951
|
-
|
|
493952
|
-
|
|
493962
|
+
if (yes) {
|
|
493963
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:自动更新配置文件中的全部云函数配置'));
|
|
493964
|
+
isBathUpdate = true;
|
|
493965
|
+
}
|
|
493966
|
+
else {
|
|
493967
|
+
const { isBatch } = yield inquirer_1.default.prompt({
|
|
493968
|
+
type: 'confirm',
|
|
493969
|
+
name: 'isBatch',
|
|
493970
|
+
message: (0, i18n_1.t)('无云函数名称,是否需要更新配置文件中的【全部云函数】的配置?'),
|
|
493971
|
+
default: false
|
|
493972
|
+
});
|
|
493973
|
+
isBathUpdate = isBatch;
|
|
493974
|
+
}
|
|
493953
493975
|
if (!isBathUpdate) {
|
|
493954
493976
|
throw new error_1.CloudBaseError((0, i18n_1.t)('请指定云函数名称!'));
|
|
493955
493977
|
}
|
|
493956
493978
|
}
|
|
493957
493979
|
if (isBathUpdate) {
|
|
493958
|
-
const envVarUpdateMode = hasEnvVariablesConfig(functions)
|
|
493980
|
+
const envVarUpdateMode = hasEnvVariablesConfig(functions)
|
|
493981
|
+
? (yes ? 'overwrite' : yield askEnvVarUpdateMode())
|
|
493982
|
+
: undefined;
|
|
493959
493983
|
for (const func of functions) {
|
|
493960
493984
|
const isValid = yield validateFunctionTypeChange(envId, func, log);
|
|
493961
493985
|
if (!isValid) {
|
|
@@ -493979,7 +494003,9 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493979
494003
|
if (!isValid) {
|
|
493980
494004
|
return;
|
|
493981
494005
|
}
|
|
493982
|
-
const envVarUpdateMode = hasEnvVariablesConfig([functionItem])
|
|
494006
|
+
const envVarUpdateMode = hasEnvVariablesConfig([functionItem])
|
|
494007
|
+
? (yes ? 'overwrite' : yield askEnvVarUpdateMode())
|
|
494008
|
+
: undefined;
|
|
493983
494009
|
yield (0, function_1.updateFunctionConfig)({
|
|
493984
494010
|
envId,
|
|
493985
494011
|
functionName: name,
|
|
@@ -672190,6 +672216,547 @@ module.exports = function (value) {
|
|
|
672190
672216
|
};
|
|
672191
672217
|
|
|
672192
672218
|
|
|
672219
|
+
/***/ }),
|
|
672220
|
+
|
|
672221
|
+
/***/ 62600:
|
|
672222
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
672223
|
+
|
|
672224
|
+
"use strict";
|
|
672225
|
+
|
|
672226
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
672227
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
672228
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
672229
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
672230
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
672231
|
+
};
|
|
672232
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
672233
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
672234
|
+
};
|
|
672235
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
672236
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
672237
|
+
};
|
|
672238
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
672239
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
672240
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
672241
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
672242
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
672243
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
672244
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
672245
|
+
});
|
|
672246
|
+
};
|
|
672247
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
672248
|
+
var t = {};
|
|
672249
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
672250
|
+
t[p] = s[p];
|
|
672251
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
672252
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
672253
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
672254
|
+
t[p[i]] = s[p[i]];
|
|
672255
|
+
}
|
|
672256
|
+
return t;
|
|
672257
|
+
};
|
|
672258
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
672259
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
672260
|
+
};
|
|
672261
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
672262
|
+
exports.ConfigPullCommand = void 0;
|
|
672263
|
+
const fs_1 = __importDefault(__webpack_require__(79896));
|
|
672264
|
+
const path_1 = __importDefault(__webpack_require__(16928));
|
|
672265
|
+
const inquirer_1 = __importDefault(__webpack_require__(6403));
|
|
672266
|
+
const common_1 = __webpack_require__(48431);
|
|
672267
|
+
const error_1 = __webpack_require__(66759);
|
|
672268
|
+
const function_1 = __webpack_require__(11686);
|
|
672269
|
+
const utils_1 = __webpack_require__(82079);
|
|
672270
|
+
const utils_2 = __webpack_require__(75213);
|
|
672271
|
+
const decorators_1 = __webpack_require__(93480);
|
|
672272
|
+
const i18n_1 = __webpack_require__(69258);
|
|
672273
|
+
const constant_1 = __webpack_require__(62977);
|
|
672274
|
+
function convertToFunctionConfig(detail, funcDir) {
|
|
672275
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
672276
|
+
const config = {
|
|
672277
|
+
name: detail.FunctionName
|
|
672278
|
+
};
|
|
672279
|
+
if (funcDir) {
|
|
672280
|
+
config.dir = funcDir;
|
|
672281
|
+
}
|
|
672282
|
+
if (detail.Type) {
|
|
672283
|
+
config.type = detail.Type;
|
|
672284
|
+
}
|
|
672285
|
+
if (detail.Handler) {
|
|
672286
|
+
config.handler = detail.Handler;
|
|
672287
|
+
}
|
|
672288
|
+
if (detail.Timeout) {
|
|
672289
|
+
config.timeout = detail.Timeout;
|
|
672290
|
+
}
|
|
672291
|
+
if (detail.Runtime) {
|
|
672292
|
+
config.runtime = detail.Runtime;
|
|
672293
|
+
}
|
|
672294
|
+
if (detail.MemorySize) {
|
|
672295
|
+
config.memorySize = detail.MemorySize;
|
|
672296
|
+
}
|
|
672297
|
+
if (detail.InstallDependency !== undefined) {
|
|
672298
|
+
config.installDependency = detail.InstallDependency === 'TRUE';
|
|
672299
|
+
}
|
|
672300
|
+
if (((_b = (_a = detail.Environment) === null || _a === void 0 ? void 0 : _a.Variables) === null || _b === void 0 ? void 0 : _b.length) > 0) {
|
|
672301
|
+
const envVariables = {};
|
|
672302
|
+
for (const item of detail.Environment.Variables) {
|
|
672303
|
+
envVariables[item.Key] = item.Value;
|
|
672304
|
+
}
|
|
672305
|
+
config.envVariables = envVariables;
|
|
672306
|
+
}
|
|
672307
|
+
if (((_c = detail.VpcConfig) === null || _c === void 0 ? void 0 : _c.VpcId) && ((_d = detail.VpcConfig) === null || _d === void 0 ? void 0 : _d.SubnetId)) {
|
|
672308
|
+
config.vpc = {
|
|
672309
|
+
vpcId: detail.VpcConfig.VpcId,
|
|
672310
|
+
subnetId: detail.VpcConfig.SubnetId
|
|
672311
|
+
};
|
|
672312
|
+
}
|
|
672313
|
+
if (((_e = detail.Triggers) === null || _e === void 0 ? void 0 : _e.length) > 0) {
|
|
672314
|
+
config.triggers = detail.Triggers.map((trigger) => ({
|
|
672315
|
+
name: trigger.TriggerName,
|
|
672316
|
+
type: trigger.Type.toLowerCase(),
|
|
672317
|
+
config: trigger.TriggerDesc
|
|
672318
|
+
}));
|
|
672319
|
+
}
|
|
672320
|
+
if (detail.ProtocolType === 'WS') {
|
|
672321
|
+
config.protocolType = 'WS';
|
|
672322
|
+
if ((_g = (_f = detail.ProtocolParams) === null || _f === void 0 ? void 0 : _f.WsParams) === null || _g === void 0 ? void 0 : _g.IdleTimeOut) {
|
|
672323
|
+
config.protocolParams = {
|
|
672324
|
+
wsParams: {
|
|
672325
|
+
idleTimeOut: detail.ProtocolParams.WsParams.IdleTimeOut
|
|
672326
|
+
}
|
|
672327
|
+
};
|
|
672328
|
+
}
|
|
672329
|
+
}
|
|
672330
|
+
if (detail.Type === 'HTTP' && detail.InstanceConcurrencyConfig) {
|
|
672331
|
+
const concurrencyConfig = {};
|
|
672332
|
+
if (detail.InstanceConcurrencyConfig.MaxConcurrency) {
|
|
672333
|
+
concurrencyConfig.maxConcurrency = detail.InstanceConcurrencyConfig.MaxConcurrency;
|
|
672334
|
+
}
|
|
672335
|
+
if (detail.InstanceConcurrencyConfig.DynamicEnabled !== undefined) {
|
|
672336
|
+
concurrencyConfig.dynamicEnabled = detail.InstanceConcurrencyConfig.DynamicEnabled;
|
|
672337
|
+
}
|
|
672338
|
+
if (Object.keys(concurrencyConfig).length > 0) {
|
|
672339
|
+
config.instanceConcurrencyConfig = concurrencyConfig;
|
|
672340
|
+
}
|
|
672341
|
+
}
|
|
672342
|
+
return config;
|
|
672343
|
+
}
|
|
672344
|
+
class FunctionModuleHandler {
|
|
672345
|
+
constructor() {
|
|
672346
|
+
this.moduleName = (0, i18n_1.t)('云函数');
|
|
672347
|
+
this.configKey = 'functions';
|
|
672348
|
+
}
|
|
672349
|
+
createDefaultConfig(funcName, funcDir) {
|
|
672350
|
+
const { installDependency } = constant_1.DefaultFunctionDeployConfig, defaultConfigWithoutInstall = __rest(constant_1.DefaultFunctionDeployConfig, ["installDependency"]);
|
|
672351
|
+
const config = Object.assign({ name: funcName }, defaultConfigWithoutInstall);
|
|
672352
|
+
if (funcDir) {
|
|
672353
|
+
config.dir = funcDir;
|
|
672354
|
+
}
|
|
672355
|
+
return config;
|
|
672356
|
+
}
|
|
672357
|
+
inferFromLocal(name, dir, log) {
|
|
672358
|
+
if (dir) {
|
|
672359
|
+
const targetDir = path_1.default.resolve(process.cwd(), dir);
|
|
672360
|
+
const inferResult = (0, function_1.inferFunctionConfig)({ name, targetDir });
|
|
672361
|
+
if (inferResult) {
|
|
672362
|
+
const config = inferResult.config;
|
|
672363
|
+
config.dir = dir;
|
|
672364
|
+
log.info((0, i18n_1.t)('✓ 已从本地推测出函数 [{{name}}] 配置(来源:{{source}},位置:{{location}})', {
|
|
672365
|
+
name,
|
|
672366
|
+
source: inferResult.source,
|
|
672367
|
+
location: dir
|
|
672368
|
+
}));
|
|
672369
|
+
return { name, config, success: true, inferred: true };
|
|
672370
|
+
}
|
|
672371
|
+
else {
|
|
672372
|
+
const config = this.createDefaultConfig(name, dir);
|
|
672373
|
+
log.info((0, i18n_1.t)('⚠ 无法推测函数 [{{name}}] 配置,使用默认配置', { name }));
|
|
672374
|
+
return { name, config, success: true, inferred: false };
|
|
672375
|
+
}
|
|
672376
|
+
}
|
|
672377
|
+
let inferResult = (0, function_1.inferFunctionConfig)({ name, targetDir: process.cwd() });
|
|
672378
|
+
let finalDir;
|
|
672379
|
+
let sourceLocation = '';
|
|
672380
|
+
if (inferResult) {
|
|
672381
|
+
finalDir = '.';
|
|
672382
|
+
sourceLocation = (0, i18n_1.t)('当前目录');
|
|
672383
|
+
}
|
|
672384
|
+
else {
|
|
672385
|
+
const standardDir = path_1.default.join(process.cwd(), 'functions', name);
|
|
672386
|
+
if (fs_1.default.existsSync(standardDir)) {
|
|
672387
|
+
inferResult = (0, function_1.inferFunctionConfig)({ name, targetDir: standardDir });
|
|
672388
|
+
if (inferResult) {
|
|
672389
|
+
finalDir = undefined;
|
|
672390
|
+
sourceLocation = (0, i18n_1.t)('标准目录 (functions/{{name}})', { name });
|
|
672391
|
+
}
|
|
672392
|
+
}
|
|
672393
|
+
}
|
|
672394
|
+
if (inferResult) {
|
|
672395
|
+
const config = inferResult.config;
|
|
672396
|
+
if (finalDir !== undefined) {
|
|
672397
|
+
config.dir = finalDir;
|
|
672398
|
+
}
|
|
672399
|
+
log.info((0, i18n_1.t)('✓ 已从本地推测出函数 [{{name}}] 配置(来源:{{source}},位置:{{location}})', {
|
|
672400
|
+
name,
|
|
672401
|
+
source: inferResult.source,
|
|
672402
|
+
location: sourceLocation
|
|
672403
|
+
}));
|
|
672404
|
+
return { name, config, success: true, inferred: true };
|
|
672405
|
+
}
|
|
672406
|
+
const config = this.createDefaultConfig(name);
|
|
672407
|
+
log.info((0, i18n_1.t)('⚠ 无法推测函数 [{{name}}] 配置,使用默认配置', { name }));
|
|
672408
|
+
return { name, config, success: true, inferred: false };
|
|
672409
|
+
}
|
|
672410
|
+
batchProcess(options) {
|
|
672411
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
672412
|
+
const { names, envId, codeSecret, dir, yes, log, loading } = options;
|
|
672413
|
+
const functionService = yield (0, function_1.getFunctionService)(envId);
|
|
672414
|
+
let inferMode = null;
|
|
672415
|
+
const results = [];
|
|
672416
|
+
for (const name of names) {
|
|
672417
|
+
try {
|
|
672418
|
+
loading.start((0, i18n_1.t)('获取函数 [{{name}}] 配置中...', { name }));
|
|
672419
|
+
const detail = yield functionService.getFunctionDetail(name, codeSecret);
|
|
672420
|
+
loading.stop();
|
|
672421
|
+
const config = convertToFunctionConfig(detail, dir || undefined);
|
|
672422
|
+
log.info((0, i18n_1.t)('✓ 已从云端拉取函数 [{{name}}] 的配置', { name }));
|
|
672423
|
+
results.push({ name, config, success: true, inferred: false });
|
|
672424
|
+
}
|
|
672425
|
+
catch (e) {
|
|
672426
|
+
loading.stop();
|
|
672427
|
+
if (e.code === 'ResourceNotFound.Function' || e.code === 'ResourceNotFound.FunctionName') {
|
|
672428
|
+
log.warn((0, i18n_1.t)('云函数 [{{name}}] 不存在', { name }));
|
|
672429
|
+
let shouldCreate = yes || inferMode === 'all';
|
|
672430
|
+
if (!shouldCreate && inferMode === null && names.length > 1) {
|
|
672431
|
+
const { mode } = yield inquirer_1.default.prompt({
|
|
672432
|
+
type: 'list',
|
|
672433
|
+
name: 'mode',
|
|
672434
|
+
message: (0, i18n_1.t)('发现不存在的函数,请选择处理方式:'),
|
|
672435
|
+
choices: [
|
|
672436
|
+
{ name: (0, i18n_1.t)('全部推测'), value: 'all' },
|
|
672437
|
+
{ name: (0, i18n_1.t)('逐个询问'), value: 'individual' },
|
|
672438
|
+
{ name: (0, i18n_1.t)('跳过所有'), value: 'skip' }
|
|
672439
|
+
]
|
|
672440
|
+
});
|
|
672441
|
+
inferMode = mode;
|
|
672442
|
+
if (inferMode === 'all') {
|
|
672443
|
+
shouldCreate = true;
|
|
672444
|
+
}
|
|
672445
|
+
else if (inferMode === 'skip') {
|
|
672446
|
+
results.push({ name, success: false, error: new Error((0, i18n_1.t)('用户跳过')) });
|
|
672447
|
+
continue;
|
|
672448
|
+
}
|
|
672449
|
+
}
|
|
672450
|
+
if (inferMode === 'skip') {
|
|
672451
|
+
results.push({ name, success: false, error: new Error((0, i18n_1.t)('用户跳过')) });
|
|
672452
|
+
continue;
|
|
672453
|
+
}
|
|
672454
|
+
if (!shouldCreate && inferMode !== 'all') {
|
|
672455
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
|
672456
|
+
type: 'confirm',
|
|
672457
|
+
name: 'confirm',
|
|
672458
|
+
message: (0, i18n_1.t)('是否从本地项目推测函数 [{{name}}] 的配置?', { name }),
|
|
672459
|
+
default: true
|
|
672460
|
+
});
|
|
672461
|
+
shouldCreate = confirm;
|
|
672462
|
+
}
|
|
672463
|
+
if (!shouldCreate) {
|
|
672464
|
+
results.push({ name, success: false, error: new Error((0, i18n_1.t)('用户取消')) });
|
|
672465
|
+
continue;
|
|
672466
|
+
}
|
|
672467
|
+
results.push(this.inferFromLocal(name, dir, log));
|
|
672468
|
+
}
|
|
672469
|
+
else {
|
|
672470
|
+
results.push({ name, success: false, error: e });
|
|
672471
|
+
}
|
|
672472
|
+
}
|
|
672473
|
+
}
|
|
672474
|
+
return results;
|
|
672475
|
+
});
|
|
672476
|
+
}
|
|
672477
|
+
getAllNamesFromConfig(config) {
|
|
672478
|
+
if (!(config === null || config === void 0 ? void 0 : config.functions) || config.functions.length === 0) {
|
|
672479
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('配置文件中未找到函数定义,请先配置函数或手动指定函数名'));
|
|
672480
|
+
}
|
|
672481
|
+
return config.functions.map((fn) => fn.name).filter(Boolean);
|
|
672482
|
+
}
|
|
672483
|
+
generateCloudbaserc(envId, configs) {
|
|
672484
|
+
return {
|
|
672485
|
+
envId,
|
|
672486
|
+
functionRoot: './functions',
|
|
672487
|
+
functions: configs
|
|
672488
|
+
};
|
|
672489
|
+
}
|
|
672490
|
+
}
|
|
672491
|
+
let ConfigPullCommand = class ConfigPullCommand extends common_1.Command {
|
|
672492
|
+
get options() {
|
|
672493
|
+
return {
|
|
672494
|
+
cmd: 'config',
|
|
672495
|
+
childCmd: 'pull <module> [name...]',
|
|
672496
|
+
options: [
|
|
672497
|
+
{
|
|
672498
|
+
flags: '-e, --envId <envId>',
|
|
672499
|
+
desc: (0, i18n_1.t)('环境 Id')
|
|
672500
|
+
},
|
|
672501
|
+
{
|
|
672502
|
+
flags: '-o, --output <output>',
|
|
672503
|
+
desc: (0, i18n_1.t)('输出文件路径(默认为当前目录下的 cloudbaserc.json)')
|
|
672504
|
+
},
|
|
672505
|
+
{
|
|
672506
|
+
flags: '--stdout',
|
|
672507
|
+
desc: (0, i18n_1.t)('输出到控制台而非文件')
|
|
672508
|
+
},
|
|
672509
|
+
{
|
|
672510
|
+
flags: '--code-secret <codeSecret>',
|
|
672511
|
+
desc: (0, i18n_1.t)('代码加密的函数的 CodeSecret')
|
|
672512
|
+
},
|
|
672513
|
+
{
|
|
672514
|
+
flags: '--dir <dir>',
|
|
672515
|
+
desc: (0, i18n_1.t)('指定目录用于推测配置(当云函数不存在时)')
|
|
672516
|
+
},
|
|
672517
|
+
{
|
|
672518
|
+
flags: '--all',
|
|
672519
|
+
desc: (0, i18n_1.t)('拉取配置文件中的所有云函数配置')
|
|
672520
|
+
},
|
|
672521
|
+
{
|
|
672522
|
+
flags: '--yes',
|
|
672523
|
+
desc: (0, i18n_1.t)('跳过交互确认,自动覆盖已存在的文件')
|
|
672524
|
+
}
|
|
672525
|
+
],
|
|
672526
|
+
desc: (0, i18n_1.t)('拉取模块配置(当前支持: fn 云函数)'),
|
|
672527
|
+
requiredEnvId: false,
|
|
672528
|
+
autoRunLogin: true
|
|
672529
|
+
};
|
|
672530
|
+
}
|
|
672531
|
+
execute(ctx, params, log) {
|
|
672532
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
672533
|
+
const module = params === null || params === void 0 ? void 0 : params[0];
|
|
672534
|
+
const names = (params === null || params === void 0 ? void 0 : params[1]) || [];
|
|
672535
|
+
if (!module) {
|
|
672536
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('请指定模块类型,当前支持: fn (云函数)'));
|
|
672537
|
+
}
|
|
672538
|
+
const handler = this.getModuleHandler(module);
|
|
672539
|
+
yield this.pullModuleConfig(ctx, handler, names, log);
|
|
672540
|
+
});
|
|
672541
|
+
}
|
|
672542
|
+
getModuleHandler(module) {
|
|
672543
|
+
const supportedModules = ['fn'];
|
|
672544
|
+
switch (module) {
|
|
672545
|
+
case 'fn':
|
|
672546
|
+
return new FunctionModuleHandler();
|
|
672547
|
+
default:
|
|
672548
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('不支持的模块类型: {{module}},当前支持: {{supported}}', {
|
|
672549
|
+
module,
|
|
672550
|
+
supported: supportedModules.join(', ')
|
|
672551
|
+
}));
|
|
672552
|
+
}
|
|
672553
|
+
}
|
|
672554
|
+
pullModuleConfig(ctx, handler, inputNames, log) {
|
|
672555
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
672556
|
+
let { envId, options, config } = ctx;
|
|
672557
|
+
const { output, codeSecret, dir, yes, stdout, all } = options;
|
|
672558
|
+
let names = [];
|
|
672559
|
+
if (all) {
|
|
672560
|
+
names = handler.getAllNamesFromConfig(config);
|
|
672561
|
+
log.info((0, i18n_1.t)('从配置文件读取到 {{count}} 个{{moduleName}}:{{names}}', {
|
|
672562
|
+
count: names.length,
|
|
672563
|
+
moduleName: handler.moduleName,
|
|
672564
|
+
names: names.join(', ')
|
|
672565
|
+
}));
|
|
672566
|
+
}
|
|
672567
|
+
else {
|
|
672568
|
+
names = [];
|
|
672569
|
+
for (const param of inputNames) {
|
|
672570
|
+
if (typeof param === 'string' && param.trim()) {
|
|
672571
|
+
const splitNames = param.split(',').map(n => n.trim()).filter(n => n);
|
|
672572
|
+
names.push(...splitNames);
|
|
672573
|
+
}
|
|
672574
|
+
}
|
|
672575
|
+
}
|
|
672576
|
+
if (names.length === 0) {
|
|
672577
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('请指定至少一个名称,或使用 --all 选项拉取配置文件中的所有项目'));
|
|
672578
|
+
}
|
|
672579
|
+
let selectedEnvId = envId;
|
|
672580
|
+
if (!selectedEnvId) {
|
|
672581
|
+
selectedEnvId = yield (0, utils_2.selectEnv)({
|
|
672582
|
+
envTypes: [constant_1.EnvType.BAAS, constant_1.EnvType.WEDA]
|
|
672583
|
+
});
|
|
672584
|
+
}
|
|
672585
|
+
const loading = (0, utils_1.loadingFactory)();
|
|
672586
|
+
try {
|
|
672587
|
+
const results = yield handler.batchProcess({
|
|
672588
|
+
names,
|
|
672589
|
+
envId: selectedEnvId,
|
|
672590
|
+
codeSecret,
|
|
672591
|
+
dir,
|
|
672592
|
+
yes,
|
|
672593
|
+
log,
|
|
672594
|
+
loading
|
|
672595
|
+
});
|
|
672596
|
+
const successConfigs = results.filter((r) => r.success).map((r) => r.config);
|
|
672597
|
+
const failedResults = results.filter((r) => !r.success);
|
|
672598
|
+
const inferredCount = results.filter((r) => r.success && r.inferred).length;
|
|
672599
|
+
log.info((0, i18n_1.t)('处理完成:成功 {{success}} 个,失败 {{failed}} 个,推测 {{inferred}} 个', {
|
|
672600
|
+
success: successConfigs.length,
|
|
672601
|
+
failed: failedResults.length,
|
|
672602
|
+
inferred: inferredCount
|
|
672603
|
+
}));
|
|
672604
|
+
if (failedResults.length > 0) {
|
|
672605
|
+
log.warn((0, i18n_1.t)('失败的项目:'));
|
|
672606
|
+
failedResults.forEach((result) => {
|
|
672607
|
+
var _a;
|
|
672608
|
+
log.error((0, i18n_1.t)(' - {{name}}: {{error}}', {
|
|
672609
|
+
name: result.name,
|
|
672610
|
+
error: ((_a = result.error) === null || _a === void 0 ? void 0 : _a.message) || (0, i18n_1.t)('未知错误')
|
|
672611
|
+
}));
|
|
672612
|
+
});
|
|
672613
|
+
}
|
|
672614
|
+
if (successConfigs.length === 0) {
|
|
672615
|
+
log.warn((0, i18n_1.t)('没有成功获取任何配置'));
|
|
672616
|
+
return;
|
|
672617
|
+
}
|
|
672618
|
+
yield this.handleOutput({
|
|
672619
|
+
handler,
|
|
672620
|
+
configs: successConfigs,
|
|
672621
|
+
envId: selectedEnvId,
|
|
672622
|
+
output,
|
|
672623
|
+
stdout,
|
|
672624
|
+
yes,
|
|
672625
|
+
log
|
|
672626
|
+
});
|
|
672627
|
+
}
|
|
672628
|
+
catch (e) {
|
|
672629
|
+
loading.stop();
|
|
672630
|
+
throw e;
|
|
672631
|
+
}
|
|
672632
|
+
});
|
|
672633
|
+
}
|
|
672634
|
+
handleOutput(options) {
|
|
672635
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
672636
|
+
const { handler, configs, envId, output, stdout, yes, log } = options;
|
|
672637
|
+
if (stdout) {
|
|
672638
|
+
const cloudbaserc = handler.generateCloudbaserc(envId, configs);
|
|
672639
|
+
const stdoutOutput = JSON.stringify(cloudbaserc, null, 2);
|
|
672640
|
+
if (configs.length === 1) {
|
|
672641
|
+
log.info((0, i18n_1.t)('{{moduleName}} [{{name}}] 配置:', {
|
|
672642
|
+
moduleName: handler.moduleName,
|
|
672643
|
+
name: configs[0].name
|
|
672644
|
+
}));
|
|
672645
|
+
}
|
|
672646
|
+
else {
|
|
672647
|
+
log.info((0, i18n_1.t)('{{count}} 个{{moduleName}}配置:', {
|
|
672648
|
+
count: configs.length,
|
|
672649
|
+
moduleName: handler.moduleName
|
|
672650
|
+
}));
|
|
672651
|
+
}
|
|
672652
|
+
console.log(stdoutOutput);
|
|
672653
|
+
log.info('');
|
|
672654
|
+
log.info((0, i18n_1.t)('提示:可将上述配置添加到 cloudbaserc.json 的 {{configKey}} 数组中', {
|
|
672655
|
+
configKey: handler.configKey
|
|
672656
|
+
}));
|
|
672657
|
+
return;
|
|
672658
|
+
}
|
|
672659
|
+
const outputPath = output
|
|
672660
|
+
? path_1.default.resolve(process.cwd(), output)
|
|
672661
|
+
: path_1.default.resolve(process.cwd(), 'cloudbaserc.json');
|
|
672662
|
+
let finalOutput;
|
|
672663
|
+
const updatedItems = [];
|
|
672664
|
+
const addedItems = [];
|
|
672665
|
+
if (fs_1.default.existsSync(outputPath)) {
|
|
672666
|
+
try {
|
|
672667
|
+
const existingContent = fs_1.default.readFileSync(outputPath, 'utf-8');
|
|
672668
|
+
const existingConfig = JSON.parse(existingContent);
|
|
672669
|
+
if (!existingConfig[handler.configKey]) {
|
|
672670
|
+
existingConfig[handler.configKey] = [];
|
|
672671
|
+
}
|
|
672672
|
+
for (const config of configs) {
|
|
672673
|
+
const existingIndex = existingConfig[handler.configKey].findIndex((item) => item.name === config.name);
|
|
672674
|
+
if (existingIndex >= 0) {
|
|
672675
|
+
let shouldUpdate = yes;
|
|
672676
|
+
if (!shouldUpdate) {
|
|
672677
|
+
const { update } = yield inquirer_1.default.prompt({
|
|
672678
|
+
type: 'confirm',
|
|
672679
|
+
name: 'update',
|
|
672680
|
+
message: (0, i18n_1.t)('{{moduleName}} [{{name}}] 配置已存在,是否更新?', {
|
|
672681
|
+
moduleName: handler.moduleName,
|
|
672682
|
+
name: config.name
|
|
672683
|
+
}),
|
|
672684
|
+
default: true
|
|
672685
|
+
});
|
|
672686
|
+
shouldUpdate = update;
|
|
672687
|
+
}
|
|
672688
|
+
if (shouldUpdate) {
|
|
672689
|
+
existingConfig[handler.configKey][existingIndex] = config;
|
|
672690
|
+
updatedItems.push(config.name);
|
|
672691
|
+
}
|
|
672692
|
+
}
|
|
672693
|
+
else {
|
|
672694
|
+
existingConfig[handler.configKey].push(config);
|
|
672695
|
+
addedItems.push(config.name);
|
|
672696
|
+
}
|
|
672697
|
+
}
|
|
672698
|
+
if (!existingConfig.envId) {
|
|
672699
|
+
existingConfig.envId = envId;
|
|
672700
|
+
}
|
|
672701
|
+
finalOutput = existingConfig;
|
|
672702
|
+
}
|
|
672703
|
+
catch (parseError) {
|
|
672704
|
+
log.warn((0, i18n_1.t)('现有配置文件解析失败'));
|
|
672705
|
+
let shouldOverwrite = yes;
|
|
672706
|
+
if (!shouldOverwrite) {
|
|
672707
|
+
const { overwrite } = yield inquirer_1.default.prompt({
|
|
672708
|
+
type: 'confirm',
|
|
672709
|
+
name: 'overwrite',
|
|
672710
|
+
message: (0, i18n_1.t)('是否覆盖现有文件?'),
|
|
672711
|
+
default: false
|
|
672712
|
+
});
|
|
672713
|
+
shouldOverwrite = overwrite;
|
|
672714
|
+
}
|
|
672715
|
+
if (!shouldOverwrite) {
|
|
672716
|
+
log.info((0, i18n_1.t)('已取消'));
|
|
672717
|
+
return;
|
|
672718
|
+
}
|
|
672719
|
+
finalOutput = handler.generateCloudbaserc(envId, configs);
|
|
672720
|
+
addedItems.push(...configs.map(c => c.name));
|
|
672721
|
+
}
|
|
672722
|
+
}
|
|
672723
|
+
else {
|
|
672724
|
+
finalOutput = handler.generateCloudbaserc(envId, configs);
|
|
672725
|
+
addedItems.push(...configs.map(c => c.name));
|
|
672726
|
+
}
|
|
672727
|
+
const jsonOutput = JSON.stringify(finalOutput, null, 2);
|
|
672728
|
+
fs_1.default.writeFileSync(outputPath, jsonOutput, 'utf-8');
|
|
672729
|
+
if (updatedItems.length > 0) {
|
|
672730
|
+
log.success((0, i18n_1.t)('已更新{{moduleName}}配置:{{names}}', {
|
|
672731
|
+
moduleName: handler.moduleName,
|
|
672732
|
+
names: updatedItems.join(', ')
|
|
672733
|
+
}));
|
|
672734
|
+
}
|
|
672735
|
+
if (addedItems.length > 0) {
|
|
672736
|
+
log.success((0, i18n_1.t)('已添加{{moduleName}}配置:{{names}}', {
|
|
672737
|
+
moduleName: handler.moduleName,
|
|
672738
|
+
names: addedItems.join(', ')
|
|
672739
|
+
}));
|
|
672740
|
+
}
|
|
672741
|
+
log.success((0, i18n_1.t)('配置已保存到 {{path}}', { path: outputPath }));
|
|
672742
|
+
});
|
|
672743
|
+
}
|
|
672744
|
+
};
|
|
672745
|
+
__decorate([
|
|
672746
|
+
(0, decorators_1.InjectParams)(),
|
|
672747
|
+
__param(0, (0, decorators_1.CmdContext)()),
|
|
672748
|
+
__param(1, (0, decorators_1.ArgsParams)()),
|
|
672749
|
+
__param(2, (0, decorators_1.Log)()),
|
|
672750
|
+
__metadata("design:type", Function),
|
|
672751
|
+
__metadata("design:paramtypes", [Object, Array, decorators_1.Logger]),
|
|
672752
|
+
__metadata("design:returntype", Promise)
|
|
672753
|
+
], ConfigPullCommand.prototype, "execute", null);
|
|
672754
|
+
ConfigPullCommand = __decorate([
|
|
672755
|
+
(0, common_1.ICommand)()
|
|
672756
|
+
], ConfigPullCommand);
|
|
672757
|
+
exports.ConfigPullCommand = ConfigPullCommand;
|
|
672758
|
+
|
|
672759
|
+
|
|
672193
672760
|
/***/ }),
|
|
672194
672761
|
|
|
672195
672762
|
/***/ 62629:
|
|
@@ -674065,15 +674632,20 @@ exports.DefaultFunctionDeployConfig = {
|
|
|
674065
674632
|
ignore: ['node_modules', 'node_modules/**/*', '.git']
|
|
674066
674633
|
};
|
|
674067
674634
|
exports.RuntimeOptions = [
|
|
674635
|
+
{ name: 'Node.js 24.11 (公测中)', value: 'Nodejs24.11', handler: 'index.main' },
|
|
674636
|
+
{ name: 'Node.js 22.21 (公测中)', value: 'Nodejs22.21', handler: 'index.main' },
|
|
674068
674637
|
{ name: 'Node.js 20.19', value: 'Nodejs20.19', handler: 'index.main' },
|
|
674069
674638
|
{ name: 'Node.js 18.15', value: 'Nodejs18.15', handler: 'index.main' },
|
|
674070
674639
|
{ name: 'Node.js 16.13', value: 'Nodejs16.13', handler: 'index.main' },
|
|
674640
|
+
{ name: 'Python 3.11', value: 'Python3.11', handler: 'index.main' },
|
|
674641
|
+
{ name: 'Python 3.10', value: 'Python3.10', handler: 'index.main' },
|
|
674071
674642
|
{ name: 'Python 3.9', value: 'Python3.9', handler: 'index.main' },
|
|
674072
674643
|
{ name: 'Python 3.7', value: 'Python3.7', handler: 'index.main' },
|
|
674073
674644
|
{ name: 'PHP 8.0', value: 'Php8.0', handler: 'index.main' },
|
|
674074
674645
|
{ name: 'PHP 7.4', value: 'Php7.4', handler: 'index.main' },
|
|
674075
674646
|
{ name: 'Java 11', value: 'Java11', handler: 'example.Hello::mainHandler' },
|
|
674076
|
-
{ name: 'Java 8', value: 'Java8', handler: 'example.Hello::mainHandler' }
|
|
674647
|
+
{ name: 'Java 8', value: 'Java8', handler: 'example.Hello::mainHandler' },
|
|
674648
|
+
{ name: 'Golang 1', value: 'Go1', handler: 'main' }
|
|
674077
674649
|
];
|
|
674078
674650
|
exports.DefaultCloudBaseConfig = {
|
|
674079
674651
|
functionRoot: './functions',
|
|
@@ -731198,6 +731770,7 @@ __exportStar(__webpack_require__(83531), exports);
|
|
|
731198
731770
|
__exportStar(__webpack_require__(12591), exports);
|
|
731199
731771
|
__exportStar(__webpack_require__(78908), exports);
|
|
731200
731772
|
__exportStar(__webpack_require__(5827), exports);
|
|
731773
|
+
__exportStar(__webpack_require__(62600), exports);
|
|
731201
731774
|
__exportStar(__webpack_require__(5892), exports);
|
|
731202
731775
|
|
|
731203
731776
|
|
|
@@ -800747,7 +801320,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
800747
801320
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
800748
801321
|
};
|
|
800749
801322
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
800750
|
-
exports.checkAndCreateBootstrap = exports.generateBootstrapContent = void 0;
|
|
801323
|
+
exports.getConfigSourceDescription = exports.inferFunctionConfig = exports.checkAndCreateBootstrap = exports.generateBootstrapContent = void 0;
|
|
800751
801324
|
const fs_1 = __importDefault(__webpack_require__(79896));
|
|
800752
801325
|
const path_1 = __importDefault(__webpack_require__(16928));
|
|
800753
801326
|
const inquirer_1 = __importDefault(__webpack_require__(6403));
|
|
@@ -800839,6 +801412,206 @@ function checkAndCreateBootstrap(functionPath, func, options = {}) {
|
|
|
800839
801412
|
});
|
|
800840
801413
|
}
|
|
800841
801414
|
exports.checkAndCreateBootstrap = checkAndCreateBootstrap;
|
|
801415
|
+
function inferFunctionConfig(options = {}) {
|
|
801416
|
+
const { name, targetDir = process.cwd(), httpFn } = options;
|
|
801417
|
+
const nodeResult = inferNodejsConfig(targetDir, name, httpFn);
|
|
801418
|
+
if (nodeResult)
|
|
801419
|
+
return nodeResult;
|
|
801420
|
+
const pythonResult = inferPythonConfig(targetDir, name, httpFn);
|
|
801421
|
+
if (pythonResult)
|
|
801422
|
+
return pythonResult;
|
|
801423
|
+
const phpResult = inferPhpConfig(targetDir, name, httpFn);
|
|
801424
|
+
if (phpResult)
|
|
801425
|
+
return phpResult;
|
|
801426
|
+
const javaResult = inferJavaConfig(targetDir, name, httpFn);
|
|
801427
|
+
if (javaResult)
|
|
801428
|
+
return javaResult;
|
|
801429
|
+
const goResult = inferGoConfig(targetDir, name, httpFn);
|
|
801430
|
+
if (goResult)
|
|
801431
|
+
return goResult;
|
|
801432
|
+
const fileBasedResult = inferByFileExtension(targetDir, name, httpFn);
|
|
801433
|
+
if (fileBasedResult)
|
|
801434
|
+
return fileBasedResult;
|
|
801435
|
+
return null;
|
|
801436
|
+
}
|
|
801437
|
+
exports.inferFunctionConfig = inferFunctionConfig;
|
|
801438
|
+
function inferNodejsConfig(targetDir, name, httpFn) {
|
|
801439
|
+
var _a;
|
|
801440
|
+
const packageJsonPath = path_1.default.join(targetDir, 'package.json');
|
|
801441
|
+
if (!fs_1.default.existsSync(packageJsonPath)) {
|
|
801442
|
+
return null;
|
|
801443
|
+
}
|
|
801444
|
+
try {
|
|
801445
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
801446
|
+
const funcName = name || packageJson.name || path_1.default.basename(targetDir);
|
|
801447
|
+
let handler = constant_1.DefaultFunctionDeployConfig.handler;
|
|
801448
|
+
if (packageJson.main) {
|
|
801449
|
+
const mainFile = path_1.default.basename(packageJson.main).replace(/\.[^.]+$/, '');
|
|
801450
|
+
handler = `${mainFile}.main`;
|
|
801451
|
+
}
|
|
801452
|
+
let runtime = constant_1.DefaultFunctionDeployConfig.runtime;
|
|
801453
|
+
if ((_a = packageJson.engines) === null || _a === void 0 ? void 0 : _a.node) {
|
|
801454
|
+
const nodeVersion = packageJson.engines.node;
|
|
801455
|
+
if (nodeVersion.includes('20')) {
|
|
801456
|
+
runtime = 'Nodejs20.19';
|
|
801457
|
+
}
|
|
801458
|
+
else if (nodeVersion.includes('16')) {
|
|
801459
|
+
runtime = 'Nodejs16.13';
|
|
801460
|
+
}
|
|
801461
|
+
}
|
|
801462
|
+
return {
|
|
801463
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime,
|
|
801464
|
+
handler, installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801465
|
+
source: (0, i18n_1.t)('Node.js 项目(package.json)')
|
|
801466
|
+
};
|
|
801467
|
+
}
|
|
801468
|
+
catch (e) {
|
|
801469
|
+
return null;
|
|
801470
|
+
}
|
|
801471
|
+
}
|
|
801472
|
+
function inferPythonConfig(targetDir, name, httpFn) {
|
|
801473
|
+
const pythonFiles = ['requirements.txt', 'setup.py', 'pyproject.toml'];
|
|
801474
|
+
const foundFile = pythonFiles.find(file => fs_1.default.existsSync(path_1.default.join(targetDir, file)));
|
|
801475
|
+
if (!foundFile) {
|
|
801476
|
+
return null;
|
|
801477
|
+
}
|
|
801478
|
+
const funcName = name || path_1.default.basename(targetDir);
|
|
801479
|
+
const entryFiles = ['main.py', 'app.py', 'index.py'];
|
|
801480
|
+
let handler = 'index.main';
|
|
801481
|
+
for (const file of entryFiles) {
|
|
801482
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, file))) {
|
|
801483
|
+
const filename = path_1.default.basename(file, '.py');
|
|
801484
|
+
handler = `${filename}.main`;
|
|
801485
|
+
break;
|
|
801486
|
+
}
|
|
801487
|
+
}
|
|
801488
|
+
return {
|
|
801489
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Python3.9', handler, installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801490
|
+
source: (0, i18n_1.t)('Python 项目({{file}})', { file: foundFile })
|
|
801491
|
+
};
|
|
801492
|
+
}
|
|
801493
|
+
function inferPhpConfig(targetDir, name, httpFn) {
|
|
801494
|
+
const composerJsonPath = path_1.default.join(targetDir, 'composer.json');
|
|
801495
|
+
let hasPhpFiles = false;
|
|
801496
|
+
try {
|
|
801497
|
+
hasPhpFiles = fs_1.default.readdirSync(targetDir).some(file => file.endsWith('.php'));
|
|
801498
|
+
}
|
|
801499
|
+
catch (e) {
|
|
801500
|
+
}
|
|
801501
|
+
if (!fs_1.default.existsSync(composerJsonPath) && !hasPhpFiles) {
|
|
801502
|
+
return null;
|
|
801503
|
+
}
|
|
801504
|
+
let funcName = name || path_1.default.basename(targetDir);
|
|
801505
|
+
let source = (0, i18n_1.t)('PHP 项目(PHP 文件)');
|
|
801506
|
+
if (fs_1.default.existsSync(composerJsonPath)) {
|
|
801507
|
+
try {
|
|
801508
|
+
const composerJson = JSON.parse(fs_1.default.readFileSync(composerJsonPath, 'utf-8'));
|
|
801509
|
+
if (!name && composerJson.name) {
|
|
801510
|
+
funcName = composerJson.name.split('/').pop() || funcName;
|
|
801511
|
+
}
|
|
801512
|
+
source = (0, i18n_1.t)('PHP 项目(composer.json)');
|
|
801513
|
+
}
|
|
801514
|
+
catch (e) {
|
|
801515
|
+
}
|
|
801516
|
+
}
|
|
801517
|
+
let handler = 'index.main';
|
|
801518
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'index.php'))) {
|
|
801519
|
+
handler = 'index.main';
|
|
801520
|
+
}
|
|
801521
|
+
return {
|
|
801522
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Php8.0', handler, installDependency: fs_1.default.existsSync(composerJsonPath) }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801523
|
+
source
|
|
801524
|
+
};
|
|
801525
|
+
}
|
|
801526
|
+
function inferJavaConfig(targetDir, name, httpFn) {
|
|
801527
|
+
const javaFiles = ['pom.xml', 'build.gradle', 'build.gradle.kts'];
|
|
801528
|
+
const foundFile = javaFiles.find(file => fs_1.default.existsSync(path_1.default.join(targetDir, file)));
|
|
801529
|
+
if (!foundFile) {
|
|
801530
|
+
return null;
|
|
801531
|
+
}
|
|
801532
|
+
let funcName = name || path_1.default.basename(targetDir);
|
|
801533
|
+
if (!name && foundFile === 'pom.xml') {
|
|
801534
|
+
const pomPath = path_1.default.join(targetDir, 'pom.xml');
|
|
801535
|
+
try {
|
|
801536
|
+
const pomContent = fs_1.default.readFileSync(pomPath, 'utf-8');
|
|
801537
|
+
const artifactIdMatch = pomContent.match(/<artifactId>([^<]+)<\/artifactId>/);
|
|
801538
|
+
if (artifactIdMatch) {
|
|
801539
|
+
funcName = artifactIdMatch[1];
|
|
801540
|
+
}
|
|
801541
|
+
}
|
|
801542
|
+
catch (e) {
|
|
801543
|
+
}
|
|
801544
|
+
}
|
|
801545
|
+
return {
|
|
801546
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Java11', handler: 'example.Hello::mainHandler', installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801547
|
+
source: (0, i18n_1.t)('Java 项目({{file}})', { file: foundFile })
|
|
801548
|
+
};
|
|
801549
|
+
}
|
|
801550
|
+
function inferGoConfig(targetDir, name, httpFn) {
|
|
801551
|
+
const goFiles = ['go.mod', 'go.sum'];
|
|
801552
|
+
const foundFile = goFiles.find(file => fs_1.default.existsSync(path_1.default.join(targetDir, file)));
|
|
801553
|
+
if (!foundFile) {
|
|
801554
|
+
return null;
|
|
801555
|
+
}
|
|
801556
|
+
let funcName = name || path_1.default.basename(targetDir);
|
|
801557
|
+
if (!name && fs_1.default.existsSync(path_1.default.join(targetDir, 'go.mod'))) {
|
|
801558
|
+
try {
|
|
801559
|
+
const goModContent = fs_1.default.readFileSync(path_1.default.join(targetDir, 'go.mod'), 'utf-8');
|
|
801560
|
+
const moduleMatch = goModContent.match(/^module\s+(.+)$/m);
|
|
801561
|
+
if (moduleMatch) {
|
|
801562
|
+
funcName = moduleMatch[1].split('/').pop() || funcName;
|
|
801563
|
+
}
|
|
801564
|
+
}
|
|
801565
|
+
catch (e) {
|
|
801566
|
+
}
|
|
801567
|
+
}
|
|
801568
|
+
return {
|
|
801569
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Go1', handler: 'main', installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801570
|
+
source: (0, i18n_1.t)('Go 项目({{file}})', { file: foundFile })
|
|
801571
|
+
};
|
|
801572
|
+
}
|
|
801573
|
+
function inferByFileExtension(targetDir, name, httpFn) {
|
|
801574
|
+
try {
|
|
801575
|
+
const files = fs_1.default.readdirSync(targetDir);
|
|
801576
|
+
const fileTypes = {
|
|
801577
|
+
js: files.filter(f => f.endsWith('.js')).length,
|
|
801578
|
+
ts: files.filter(f => f.endsWith('.ts')).length,
|
|
801579
|
+
py: files.filter(f => f.endsWith('.py')).length,
|
|
801580
|
+
php: files.filter(f => f.endsWith('.php')).length,
|
|
801581
|
+
java: files.filter(f => f.endsWith('.java')).length,
|
|
801582
|
+
go: files.filter(f => f.endsWith('.go')).length
|
|
801583
|
+
};
|
|
801584
|
+
const maxType = Object.entries(fileTypes).reduce((a, b) => (fileTypes[a[0]] || 0) > (fileTypes[b[0]] || 0) ? a : b);
|
|
801585
|
+
if (maxType[1] === 0) {
|
|
801586
|
+
return null;
|
|
801587
|
+
}
|
|
801588
|
+
const funcName = name || path_1.default.basename(targetDir);
|
|
801589
|
+
const typeConfigMap = {
|
|
801590
|
+
js: { runtime: 'Nodejs18.15', handler: 'index.main', source: (0, i18n_1.t)('JavaScript 文件推测') },
|
|
801591
|
+
ts: { runtime: 'Nodejs18.15', handler: 'index.main', source: (0, i18n_1.t)('TypeScript 文件推测') },
|
|
801592
|
+
py: { runtime: 'Python3.9', handler: 'index.main', source: (0, i18n_1.t)('Python 文件推测') },
|
|
801593
|
+
php: { runtime: 'Php8.0', handler: 'index.main', source: (0, i18n_1.t)('PHP 文件推测') },
|
|
801594
|
+
java: { runtime: 'Java11', handler: 'example.Hello::mainHandler', source: (0, i18n_1.t)('Java 文件推测') },
|
|
801595
|
+
go: { runtime: 'Go1', handler: 'main', source: (0, i18n_1.t)('Go 文件推测') }
|
|
801596
|
+
};
|
|
801597
|
+
const typeConfig = typeConfigMap[maxType[0]];
|
|
801598
|
+
if (!typeConfig) {
|
|
801599
|
+
return null;
|
|
801600
|
+
}
|
|
801601
|
+
return {
|
|
801602
|
+
config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: typeConfig.runtime, handler: typeConfig.handler }), (httpFn ? { type: 'HTTP' } : {})),
|
|
801603
|
+
source: typeConfig.source
|
|
801604
|
+
};
|
|
801605
|
+
}
|
|
801606
|
+
catch (e) {
|
|
801607
|
+
return null;
|
|
801608
|
+
}
|
|
801609
|
+
}
|
|
801610
|
+
function getConfigSourceDescription(targetDir) {
|
|
801611
|
+
const result = inferFunctionConfig({ targetDir, name: 'temp' });
|
|
801612
|
+
return (result === null || result === void 0 ? void 0 : result.source) || (0, i18n_1.t)('默认配置');
|
|
801613
|
+
}
|
|
801614
|
+
exports.getConfigSourceDescription = getConfigSourceDescription;
|
|
800842
801615
|
|
|
800843
801616
|
|
|
800844
801617
|
/***/ }),
|
|
@@ -834840,6 +835613,10 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834840
835613
|
{
|
|
834841
835614
|
flags: '--deployMode <deployMode>',
|
|
834842
835615
|
desc: (0, i18n_1.t)('代码上传方式:cos(通过 COS 上传)或 zip(直接 ZIP 上传),默认自动选择')
|
|
835616
|
+
},
|
|
835617
|
+
{
|
|
835618
|
+
flags: '--yes',
|
|
835619
|
+
desc: (0, i18n_1.t)('跳过交互确认,使用推测或默认配置自动部署')
|
|
834843
835620
|
}
|
|
834844
835621
|
],
|
|
834845
835622
|
desc: (0, i18n_1.t)('部署云函数'),
|
|
@@ -834851,7 +835628,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834851
835628
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834852
835629
|
let { envId, config, options } = ctx;
|
|
834853
835630
|
const { functions } = config;
|
|
834854
|
-
const { force, codeSecret, path: access, all, dir, httpFn, ws, deployMode } = options;
|
|
835631
|
+
const { force, codeSecret, path: access, all, dir, httpFn, ws, deployMode, yes } = options;
|
|
834855
835632
|
const name = params === null || params === void 0 ? void 0 : params[0];
|
|
834856
835633
|
this.validateOptions({ deployMode, access }, log);
|
|
834857
835634
|
const isUnresolvedEnvId = !envId || envId.startsWith('{{');
|
|
@@ -834871,12 +835648,12 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834871
835648
|
if (hasConfig) {
|
|
834872
835649
|
return this.deployWithConfig({
|
|
834873
835650
|
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode,
|
|
834874
|
-
all, functions, functionRootPath, log
|
|
835651
|
+
all, functions, functionRootPath, yes, log
|
|
834875
835652
|
});
|
|
834876
835653
|
}
|
|
834877
835654
|
else {
|
|
834878
835655
|
return this.deployWithoutConfig({
|
|
834879
|
-
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, log
|
|
835656
|
+
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, yes, log
|
|
834880
835657
|
});
|
|
834881
835658
|
}
|
|
834882
835659
|
});
|
|
@@ -834895,11 +835672,11 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834895
835672
|
}
|
|
834896
835673
|
deployWithConfig(options) {
|
|
834897
835674
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834898
|
-
const { name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, all, functions, functionRootPath, log } = options;
|
|
835675
|
+
const { name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, all, functions, functionRootPath, yes, log } = options;
|
|
834899
835676
|
if (name) {
|
|
834900
835677
|
return this.deploySingleWithConfig({
|
|
834901
835678
|
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode,
|
|
834902
|
-
functions, functionRootPath, log
|
|
835679
|
+
functions, functionRootPath, yes, log
|
|
834903
835680
|
});
|
|
834904
835681
|
}
|
|
834905
835682
|
if (dir) {
|
|
@@ -834907,13 +835684,13 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834907
835684
|
}
|
|
834908
835685
|
return this.deployAllFunction({
|
|
834909
835686
|
all, envId, force, access, functions, codeSecret,
|
|
834910
|
-
functionRootPath, httpFn, ws, deployMode, log
|
|
835687
|
+
functionRootPath, httpFn, ws, deployMode, yes, log
|
|
834911
835688
|
});
|
|
834912
835689
|
});
|
|
834913
835690
|
}
|
|
834914
835691
|
deploySingleWithConfig(options) {
|
|
834915
835692
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834916
|
-
const { name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, functions, functionRootPath, log } = options;
|
|
835693
|
+
const { name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, functions, functionRootPath, yes, log } = options;
|
|
834917
835694
|
let func = functions === null || functions === void 0 ? void 0 : functions.find((item) => item.name === name);
|
|
834918
835695
|
let funcPath;
|
|
834919
835696
|
if (dir) {
|
|
@@ -834936,21 +835713,32 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834936
835713
|
}
|
|
834937
835714
|
if (!func) {
|
|
834938
835715
|
log.warn((0, i18n_1.t)('配置文件中未找到函数 [{{name}}] 的配置', { name }));
|
|
834939
|
-
|
|
834940
|
-
|
|
834941
|
-
|
|
834942
|
-
|
|
834943
|
-
|
|
834944
|
-
|
|
834945
|
-
|
|
834946
|
-
|
|
834947
|
-
|
|
834948
|
-
|
|
834949
|
-
|
|
834950
|
-
|
|
834951
|
-
|
|
835716
|
+
if (yes) {
|
|
835717
|
+
const inferredConfig = this.inferFunctionConfig(httpFn, funcPath);
|
|
835718
|
+
const runtime = (inferredConfig === null || inferredConfig === void 0 ? void 0 : inferredConfig.runtime) || (yield this.getDefaultRuntime(funcPath));
|
|
835719
|
+
const defaultFunc = Object.assign(Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { runtime }), inferredConfig);
|
|
835720
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:自动使用以下配置部署:'));
|
|
835721
|
+
const sourceDesc = inferredConfig ? this.getConfigSourceDescription(funcPath) : (0, i18n_1.t)('默认配置');
|
|
835722
|
+
this.printFunctionConfig(defaultFunc, log, sourceDesc);
|
|
835723
|
+
func = defaultFunc;
|
|
835724
|
+
}
|
|
835725
|
+
else {
|
|
835726
|
+
const runtime = yield this.selectRuntime();
|
|
835727
|
+
const defaultFunc = Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { runtime });
|
|
835728
|
+
log.info((0, i18n_1.t)('将使用以下默认配置:'));
|
|
835729
|
+
this.printFunctionConfig(defaultFunc, log, (0, i18n_1.t)('默认配置'));
|
|
835730
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
|
835731
|
+
type: 'confirm',
|
|
835732
|
+
name: 'confirm',
|
|
835733
|
+
message: (0, i18n_1.t)('是否使用默认配置继续部署?'),
|
|
835734
|
+
default: false
|
|
835735
|
+
});
|
|
835736
|
+
if (!confirm) {
|
|
835737
|
+
log.info((0, i18n_1.t)('已取消部署,请在配置文件中添加函数 [{{name}}] 的配置后重试', { name }));
|
|
835738
|
+
return;
|
|
835739
|
+
}
|
|
835740
|
+
func = defaultFunc;
|
|
834952
835741
|
}
|
|
834953
|
-
func = defaultFunc;
|
|
834954
835742
|
}
|
|
834955
835743
|
if (httpFn) {
|
|
834956
835744
|
func = Object.assign(Object.assign({}, func), { type: 'HTTP' });
|
|
@@ -834960,95 +835748,177 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834960
835748
|
}
|
|
834961
835749
|
return this.doDeploySingleFunction({
|
|
834962
835750
|
func, envId, force, codeSecret, access, deployMode,
|
|
834963
|
-
functionRootPath, functionPath: funcPath, log
|
|
835751
|
+
functionRootPath, functionPath: funcPath, yes, log
|
|
834964
835752
|
});
|
|
834965
835753
|
});
|
|
834966
835754
|
}
|
|
834967
835755
|
deployWithoutConfig(options) {
|
|
834968
835756
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834969
|
-
const {
|
|
834970
|
-
|
|
834971
|
-
|
|
834972
|
-
|
|
834973
|
-
|
|
834974
|
-
|
|
834975
|
-
}
|
|
834976
|
-
deployDir = path_1.default.resolve(process.cwd(), dir);
|
|
834977
|
-
log.info((0, i18n_1.t)('将从目录 {{dir}} 部署云函数', { dir: deployDir }));
|
|
835757
|
+
const { envId, codeSecret, httpFn, ws, log } = options;
|
|
835758
|
+
const { deployDir, functionName } = this.resolveFunctionInfo(options);
|
|
835759
|
+
log.verbose((0, i18n_1.t)('正在检测云端函数状态...'));
|
|
835760
|
+
let checkResult;
|
|
835761
|
+
try {
|
|
835762
|
+
checkResult = yield this.checkCloudFunction(functionName, envId, codeSecret);
|
|
834978
835763
|
}
|
|
834979
|
-
|
|
834980
|
-
|
|
835764
|
+
catch (error) {
|
|
835765
|
+
this.displayFriendlyError(error, {
|
|
835766
|
+
functionName,
|
|
835767
|
+
operation: '前置检测'
|
|
835768
|
+
}, log);
|
|
835769
|
+
checkResult = { uncertain: true, exists: false };
|
|
834981
835770
|
}
|
|
834982
835771
|
let inferredConfig = this.inferFunctionConfig(httpFn, deployDir);
|
|
834983
835772
|
const isInferred = !!inferredConfig;
|
|
834984
835773
|
if (!inferredConfig) {
|
|
834985
|
-
inferredConfig = Object.assign(Object.assign(Object.assign({ name:
|
|
835774
|
+
inferredConfig = Object.assign(Object.assign(Object.assign({ name: functionName }, constant_1.DefaultFunctionDeployConfig), (httpFn ? { type: 'HTTP' } : {})), (ws ? { type: 'HTTP', protocolType: 'WS' } : {}));
|
|
834986
835775
|
}
|
|
834987
|
-
else
|
|
834988
|
-
inferredConfig.name =
|
|
835776
|
+
else {
|
|
835777
|
+
inferredConfig.name = functionName;
|
|
834989
835778
|
}
|
|
834990
835779
|
if (ws && isInferred) {
|
|
834991
835780
|
inferredConfig = Object.assign(Object.assign({}, inferredConfig), { type: 'HTTP', protocolType: 'WS' });
|
|
834992
835781
|
}
|
|
834993
|
-
if (
|
|
834994
|
-
|
|
835782
|
+
if (checkResult.uncertain) {
|
|
835783
|
+
return yield this.handleNewFunction(inferredConfig, isInferred, options, deployDir);
|
|
835784
|
+
}
|
|
835785
|
+
else if (checkResult.exists) {
|
|
835786
|
+
return yield this.handleExistingFunction(checkResult, inferredConfig, isInferred, options, deployDir);
|
|
834995
835787
|
}
|
|
834996
835788
|
else {
|
|
834997
|
-
|
|
835789
|
+
return yield this.handleNewFunction(inferredConfig, isInferred, options, deployDir);
|
|
834998
835790
|
}
|
|
834999
|
-
|
|
835000
|
-
|
|
835001
|
-
|
|
835002
|
-
|
|
835003
|
-
|
|
835004
|
-
|
|
835005
|
-
|
|
835006
|
-
|
|
835007
|
-
|
|
835008
|
-
|
|
835791
|
+
});
|
|
835792
|
+
}
|
|
835793
|
+
resolveFunctionInfo(options) {
|
|
835794
|
+
const { name, dir, log } = options;
|
|
835795
|
+
let deployDir = process.cwd();
|
|
835796
|
+
if (dir) {
|
|
835797
|
+
(0, utils_1.checkFullAccess)(dir, true);
|
|
835798
|
+
if (!(0, utils_1.isDirectory)(dir)) {
|
|
835799
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
|
|
835800
|
+
}
|
|
835801
|
+
deployDir = path_1.default.resolve(process.cwd(), dir);
|
|
835802
|
+
log.info((0, i18n_1.t)('将从目录 {{dir}} 部署云函数', { dir: deployDir }));
|
|
835803
|
+
}
|
|
835804
|
+
else {
|
|
835805
|
+
log.info((0, i18n_1.t)('未找到配置文件,将从当前目录部署云函数'));
|
|
835806
|
+
}
|
|
835807
|
+
const functionName = name || path_1.default.basename(deployDir);
|
|
835808
|
+
return { deployDir, functionName };
|
|
835809
|
+
}
|
|
835810
|
+
handleExistingFunction(checkResult, inferredConfig, isInferred, options, deployDir) {
|
|
835811
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
835812
|
+
const { envId, force, codeSecret, access, deployMode, yes, log } = options;
|
|
835813
|
+
const conflicts = this.detectConfigConflicts(inferredConfig, checkResult.functionDetail);
|
|
835814
|
+
if (conflicts.length > 0) {
|
|
835815
|
+
this.displayConfigConflicts(inferredConfig.name, conflicts);
|
|
835816
|
+
throw new error_1.CloudBaseError((0, i18n_1.t)('配置冲突,无法部署'));
|
|
835817
|
+
}
|
|
835818
|
+
let shouldUpdate = force || yes;
|
|
835819
|
+
if (!shouldUpdate) {
|
|
835820
|
+
shouldUpdate = yield this.confirmUpdate(inferredConfig.name);
|
|
835821
|
+
if (!shouldUpdate) {
|
|
835822
|
+
log.info((0, i18n_1.t)('已取消部署'));
|
|
835823
|
+
return;
|
|
835824
|
+
}
|
|
835825
|
+
}
|
|
835826
|
+
const mergedConfig = this.mergeCloudAndLocalConfig(checkResult.functionDetail, inferredConfig);
|
|
835827
|
+
log.info((0, i18n_1.t)('✓ 函数已存在,将使用以下合并配置更新:'));
|
|
835828
|
+
this.displayMergedConfig(inferredConfig.name, mergedConfig, isInferred ? 'inferred' : 'default');
|
|
835829
|
+
let finalConfig = mergedConfig;
|
|
835830
|
+
if (!yes) {
|
|
835831
|
+
const { action } = yield inquirer_1.default.prompt({
|
|
835832
|
+
type: 'list',
|
|
835833
|
+
name: 'action',
|
|
835834
|
+
message: (0, i18n_1.t)('请选择操作'),
|
|
835835
|
+
choices: [
|
|
835836
|
+
{ name: (0, i18n_1.t)('使用合并配置更新'), value: 'update' },
|
|
835837
|
+
{ name: (0, i18n_1.t)('手动输入配置'), value: 'manual' },
|
|
835838
|
+
{ name: (0, i18n_1.t)('退出'), value: 'exit' }
|
|
835839
|
+
]
|
|
835840
|
+
});
|
|
835841
|
+
if (action === 'exit') {
|
|
835842
|
+
log.info((0, i18n_1.t)('已取消部署'));
|
|
835843
|
+
return;
|
|
835844
|
+
}
|
|
835845
|
+
if (action === 'manual') {
|
|
835846
|
+
finalConfig = yield this.promptFunctionConfig(mergedConfig, options.httpFn, options.ws);
|
|
835847
|
+
}
|
|
835848
|
+
}
|
|
835849
|
+
return yield this.doDeploySingleFunction({
|
|
835850
|
+
func: finalConfig,
|
|
835851
|
+
envId,
|
|
835852
|
+
force: true,
|
|
835853
|
+
codeSecret,
|
|
835854
|
+
access,
|
|
835855
|
+
deployMode,
|
|
835856
|
+
functionRootPath: deployDir,
|
|
835857
|
+
functionPath: '.',
|
|
835858
|
+
yes,
|
|
835859
|
+
log,
|
|
835860
|
+
preCheckResult: checkResult
|
|
835009
835861
|
});
|
|
835010
|
-
|
|
835011
|
-
|
|
835012
|
-
|
|
835862
|
+
});
|
|
835863
|
+
}
|
|
835864
|
+
handleNewFunction(inferredConfig, isInferred, options, deployDir) {
|
|
835865
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
835866
|
+
const { envId, force, codeSecret, access, deployMode, yes, log } = options;
|
|
835867
|
+
const sourceDesc = isInferred ? this.getConfigSourceDescription(deployDir) : (0, i18n_1.t)('默认配置');
|
|
835868
|
+
if (isInferred) {
|
|
835869
|
+
log.info((0, i18n_1.t)('✓ 从项目文件推测出以下配置:'));
|
|
835870
|
+
}
|
|
835871
|
+
else {
|
|
835872
|
+
log.info((0, i18n_1.t)('⚠ 未推测出配置,将使用默认配置:'));
|
|
835013
835873
|
}
|
|
835014
|
-
|
|
835015
|
-
|
|
835016
|
-
|
|
835874
|
+
this.printFunctionConfig(inferredConfig, log, sourceDesc);
|
|
835875
|
+
let finalConfig = inferredConfig;
|
|
835876
|
+
if (yes) {
|
|
835877
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:跳过交互,自动部署'));
|
|
835017
835878
|
}
|
|
835018
835879
|
else {
|
|
835019
|
-
|
|
835880
|
+
const { action } = yield inquirer_1.default.prompt({
|
|
835881
|
+
type: 'list',
|
|
835882
|
+
name: 'action',
|
|
835883
|
+
message: (0, i18n_1.t)('请选择操作'),
|
|
835884
|
+
choices: [
|
|
835885
|
+
{ name: (0, i18n_1.t)('使用当前配置部署'), value: 'deploy' },
|
|
835886
|
+
{ name: (0, i18n_1.t)('手动输入配置'), value: 'manual' },
|
|
835887
|
+
{ name: (0, i18n_1.t)('退出'), value: 'exit' }
|
|
835888
|
+
]
|
|
835889
|
+
});
|
|
835890
|
+
if (action === 'exit') {
|
|
835891
|
+
log.info((0, i18n_1.t)('已取消部署'));
|
|
835892
|
+
return;
|
|
835893
|
+
}
|
|
835894
|
+
if (action === 'manual') {
|
|
835895
|
+
finalConfig = yield this.promptFunctionConfig(inferredConfig, options.httpFn, options.ws);
|
|
835896
|
+
}
|
|
835020
835897
|
}
|
|
835021
|
-
return this.doDeploySingleFunction({
|
|
835022
|
-
func
|
|
835023
|
-
|
|
835898
|
+
return yield this.doDeploySingleFunction({
|
|
835899
|
+
func: finalConfig,
|
|
835900
|
+
envId,
|
|
835901
|
+
force,
|
|
835902
|
+
codeSecret,
|
|
835903
|
+
access,
|
|
835904
|
+
deployMode,
|
|
835905
|
+
functionRootPath: deployDir,
|
|
835906
|
+
functionPath: '.',
|
|
835907
|
+
yes,
|
|
835908
|
+
log
|
|
835024
835909
|
});
|
|
835025
835910
|
});
|
|
835026
835911
|
}
|
|
835027
835912
|
inferFunctionConfig(httpFn, deployDir) {
|
|
835028
835913
|
const targetDir = deployDir || process.cwd();
|
|
835029
|
-
const
|
|
835030
|
-
|
|
835031
|
-
return null;
|
|
835032
|
-
}
|
|
835033
|
-
try {
|
|
835034
|
-
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
835035
|
-
if (!packageJson.name) {
|
|
835036
|
-
return null;
|
|
835037
|
-
}
|
|
835038
|
-
let handler = constant_1.DefaultFunctionDeployConfig.handler;
|
|
835039
|
-
if (packageJson.main) {
|
|
835040
|
-
const mainFile = path_1.default.basename(packageJson.main).replace(/\.[^.]+$/, '');
|
|
835041
|
-
handler = `${mainFile}.main`;
|
|
835042
|
-
}
|
|
835043
|
-
return Object.assign(Object.assign(Object.assign({ name: packageJson.name }, constant_1.DefaultFunctionDeployConfig), { handler }), (httpFn ? { type: 'HTTP' } : {}));
|
|
835044
|
-
}
|
|
835045
|
-
catch (e) {
|
|
835046
|
-
return null;
|
|
835047
|
-
}
|
|
835914
|
+
const result = (0, function_1.inferFunctionConfig)({ targetDir, httpFn });
|
|
835915
|
+
return (result === null || result === void 0 ? void 0 : result.config) || null;
|
|
835048
835916
|
}
|
|
835049
|
-
promptFunctionConfig(defaultConfig, httpFn) {
|
|
835917
|
+
promptFunctionConfig(defaultConfig, httpFn, ws) {
|
|
835050
835918
|
var _a, _b, _c;
|
|
835051
835919
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835920
|
+
const isHttpFnFromCli = httpFn || ws;
|
|
835921
|
+
const isWsFromCli = ws;
|
|
835052
835922
|
const answers = yield inquirer_1.default.prompt([
|
|
835053
835923
|
{
|
|
835054
835924
|
type: 'input',
|
|
@@ -835077,62 +835947,49 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835077
835947
|
name: 'handler',
|
|
835078
835948
|
message: (0, i18n_1.t)('入口函数(格式:文件名.函数名)'),
|
|
835079
835949
|
default: (answers) => {
|
|
835950
|
+
if (defaultConfig.handler) {
|
|
835951
|
+
return defaultConfig.handler;
|
|
835952
|
+
}
|
|
835080
835953
|
const selectedRuntime = constant_1.RuntimeOptions.find(r => r.value === answers.runtime);
|
|
835081
|
-
return (selectedRuntime === null || selectedRuntime === void 0 ? void 0 : selectedRuntime.handler) ||
|
|
835954
|
+
return (selectedRuntime === null || selectedRuntime === void 0 ? void 0 : selectedRuntime.handler) || constant_1.DefaultFunctionDeployConfig.handler;
|
|
835082
835955
|
}
|
|
835083
835956
|
},
|
|
835084
835957
|
{
|
|
835085
835958
|
type: 'confirm',
|
|
835086
835959
|
name: 'isHttpFn',
|
|
835087
835960
|
message: (0, i18n_1.t)('是否为 HTTP 函数'),
|
|
835088
|
-
default:
|
|
835089
|
-
when: !
|
|
835961
|
+
default: isHttpFnFromCli || defaultConfig.type === 'HTTP',
|
|
835962
|
+
when: !isHttpFnFromCli
|
|
835090
835963
|
},
|
|
835091
835964
|
{
|
|
835092
835965
|
type: 'confirm',
|
|
835093
835966
|
name: 'enableWebSocket',
|
|
835094
835967
|
message: (0, i18n_1.t)('是否支持 WebSocket 协议'),
|
|
835095
|
-
default: defaultConfig.protocolType === 'WS',
|
|
835096
|
-
when: (answers) =>
|
|
835968
|
+
default: isWsFromCli || defaultConfig.protocolType === 'WS',
|
|
835969
|
+
when: (answers) => !isWsFromCli && (isHttpFnFromCli || answers.isHttpFn)
|
|
835097
835970
|
},
|
|
835098
835971
|
{
|
|
835099
835972
|
type: 'number',
|
|
835100
835973
|
name: 'timeout',
|
|
835101
835974
|
message: (answers) => {
|
|
835102
|
-
const isWs = answers.enableWebSocket;
|
|
835975
|
+
const isWs = isWsFromCli || answers.enableWebSocket;
|
|
835103
835976
|
return isWs ? (0, i18n_1.t)('超时时间(秒,1-7200)') : (0, i18n_1.t)('超时时间(秒,1-900)');
|
|
835104
835977
|
},
|
|
835105
835978
|
default: defaultConfig.timeout,
|
|
835106
|
-
validate: (input, answers) => {
|
|
835107
|
-
const num = Number(input);
|
|
835108
|
-
const isWs = answers.enableWebSocket;
|
|
835109
|
-
const maxTimeout = isWs ? 7200 : 900;
|
|
835110
|
-
if (isNaN(num) || num < 1 || num > maxTimeout) {
|
|
835111
|
-
return isWs ? (0, i18n_1.t)('超时时间必须在 1-7200 秒之间') : (0, i18n_1.t)('超时时间必须在 1-900 秒之间');
|
|
835112
|
-
}
|
|
835113
|
-
return true;
|
|
835114
|
-
}
|
|
835115
835979
|
},
|
|
835116
835980
|
{
|
|
835117
835981
|
type: 'number',
|
|
835118
835982
|
name: 'idleTimeOut',
|
|
835119
835983
|
message: (0, i18n_1.t)('空闲超时时间(秒,10-7200,默认15)'),
|
|
835120
835984
|
default: ((_b = (_a = defaultConfig.protocolParams) === null || _a === void 0 ? void 0 : _a.wsParams) === null || _b === void 0 ? void 0 : _b.idleTimeOut) || 15,
|
|
835121
|
-
when: (answers) => answers.enableWebSocket,
|
|
835122
|
-
validate: (input) => {
|
|
835123
|
-
const num = Number(input);
|
|
835124
|
-
if (isNaN(num) || num < 10 || num > 7200) {
|
|
835125
|
-
return (0, i18n_1.t)('空闲超时时间必须在 10-7200 秒之间');
|
|
835126
|
-
}
|
|
835127
|
-
return true;
|
|
835128
|
-
}
|
|
835985
|
+
when: (answers) => isWsFromCli || answers.enableWebSocket,
|
|
835129
835986
|
},
|
|
835130
835987
|
{
|
|
835131
835988
|
type: 'confirm',
|
|
835132
835989
|
name: 'enableInstanceConcurrency',
|
|
835133
835990
|
message: (0, i18n_1.t)('是否启用多并发'),
|
|
835134
835991
|
default: !!defaultConfig.instanceConcurrencyConfig,
|
|
835135
|
-
when: (answers) =>
|
|
835992
|
+
when: (answers) => isHttpFnFromCli || answers.isHttpFn
|
|
835136
835993
|
},
|
|
835137
835994
|
{
|
|
835138
835995
|
type: 'number',
|
|
@@ -835168,15 +836025,16 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835168
836025
|
default: defaultConfig.installDependency
|
|
835169
836026
|
}
|
|
835170
836027
|
]);
|
|
835171
|
-
const
|
|
835172
|
-
const
|
|
836028
|
+
const enableWs = isWsFromCli || answers.enableWebSocket;
|
|
836029
|
+
const protocolType = enableWs ? 'WS' : undefined;
|
|
836030
|
+
const protocolParams = (enableWs && answers.idleTimeOut) ? {
|
|
835173
836031
|
wsParams: { idleTimeOut: answers.idleTimeOut }
|
|
835174
836032
|
} : undefined;
|
|
835175
836033
|
const instanceConcurrencyConfig = answers.enableInstanceConcurrency ? {
|
|
835176
836034
|
dynamicEnabled: 'FALSE',
|
|
835177
836035
|
maxConcurrency: answers.maxConcurrency
|
|
835178
836036
|
} : undefined;
|
|
835179
|
-
return Object.assign(Object.assign(Object.assign(Object.assign({ name: answers.name.trim(), runtime: answers.runtime, handler: answers.handler, timeout: answers.timeout, memorySize: answers.memorySize, installDependency: answers.installDependency, ignore: defaultConfig.ignore || constant_1.DefaultFunctionDeployConfig.ignore }, (
|
|
836037
|
+
return Object.assign(Object.assign(Object.assign(Object.assign({ name: answers.name.trim(), runtime: answers.runtime, handler: answers.handler, timeout: answers.timeout, memorySize: answers.memorySize, installDependency: answers.installDependency, ignore: defaultConfig.ignore || constant_1.DefaultFunctionDeployConfig.ignore }, (isHttpFnFromCli || answers.isHttpFn ? { type: 'HTTP' } : {})), (protocolType ? { protocolType } : {})), (protocolParams ? { protocolParams } : {})), (instanceConcurrencyConfig ? { instanceConcurrencyConfig } : {}));
|
|
835180
836038
|
});
|
|
835181
836039
|
}
|
|
835182
836040
|
promptFunctionName() {
|
|
@@ -835195,8 +836053,11 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835195
836053
|
return funcName.trim();
|
|
835196
836054
|
});
|
|
835197
836055
|
}
|
|
835198
|
-
printFunctionConfig(func, log) {
|
|
836056
|
+
printFunctionConfig(func, log, source) {
|
|
835199
836057
|
var _a, _b;
|
|
836058
|
+
if (source) {
|
|
836059
|
+
log.info((0, i18n_1.t)('配置来源:{{source}}', { source }));
|
|
836060
|
+
}
|
|
835200
836061
|
log.info((0, i18n_1.t)(' - 函数名称:{{name}}', { name: func.name }));
|
|
835201
836062
|
log.info((0, i18n_1.t)(' - 运行时:{{runtime}}', { runtime: func.runtime }));
|
|
835202
836063
|
log.info((0, i18n_1.t)(' - 入口函数:{{handler}}', { handler: func.handler }));
|
|
@@ -835219,10 +836080,65 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835219
836080
|
log.info((0, i18n_1.t)(' - 单实例最大并发数:{{num}}', { num: func.instanceConcurrencyConfig.maxConcurrency }));
|
|
835220
836081
|
}
|
|
835221
836082
|
}
|
|
836083
|
+
else {
|
|
836084
|
+
log.info((0, i18n_1.t)(' - 函数类型:Event(事件触发)'));
|
|
836085
|
+
}
|
|
836086
|
+
if (func.envVariables && Object.keys(func.envVariables).length > 0) {
|
|
836087
|
+
log.info((0, i18n_1.t)(' - 环境变量:{{count}} 个', { count: Object.keys(func.envVariables).length }));
|
|
836088
|
+
}
|
|
836089
|
+
if (func.vpc) {
|
|
836090
|
+
log.info((0, i18n_1.t)(' - VPC 配置:已配置'));
|
|
836091
|
+
}
|
|
836092
|
+
}
|
|
836093
|
+
getConfigSourceDescription(targetDir) {
|
|
836094
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'package.json'))) {
|
|
836095
|
+
return (0, i18n_1.t)('Node.js 项目(package.json)');
|
|
836096
|
+
}
|
|
836097
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'requirements.txt'))) {
|
|
836098
|
+
return (0, i18n_1.t)('Python 项目(requirements.txt)');
|
|
836099
|
+
}
|
|
836100
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'setup.py'))) {
|
|
836101
|
+
return (0, i18n_1.t)('Python 项目(setup.py)');
|
|
836102
|
+
}
|
|
836103
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'pyproject.toml'))) {
|
|
836104
|
+
return (0, i18n_1.t)('Python 项目(pyproject.toml)');
|
|
836105
|
+
}
|
|
836106
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'composer.json'))) {
|
|
836107
|
+
return (0, i18n_1.t)('PHP 项目(composer.json)');
|
|
836108
|
+
}
|
|
836109
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'pom.xml'))) {
|
|
836110
|
+
return (0, i18n_1.t)('Java 项目(pom.xml)');
|
|
836111
|
+
}
|
|
836112
|
+
if (fs_1.default.existsSync(path_1.default.join(targetDir, 'build.gradle'))) {
|
|
836113
|
+
return (0, i18n_1.t)('Java 项目(build.gradle)');
|
|
836114
|
+
}
|
|
836115
|
+
try {
|
|
836116
|
+
const files = fs_1.default.readdirSync(targetDir);
|
|
836117
|
+
const fileTypes = {
|
|
836118
|
+
js: files.filter(f => f.endsWith('.js')).length,
|
|
836119
|
+
ts: files.filter(f => f.endsWith('.ts')).length,
|
|
836120
|
+
py: files.filter(f => f.endsWith('.py')).length,
|
|
836121
|
+
php: files.filter(f => f.endsWith('.php')).length,
|
|
836122
|
+
java: files.filter(f => f.endsWith('.java')).length
|
|
836123
|
+
};
|
|
836124
|
+
const maxType = Object.entries(fileTypes).reduce((a, b) => fileTypes[a[0]] > fileTypes[b[0]] ? a : b);
|
|
836125
|
+
if (maxType[1] > 0) {
|
|
836126
|
+
switch (maxType[0]) {
|
|
836127
|
+
case 'js': return (0, i18n_1.t)('JavaScript 文件推测');
|
|
836128
|
+
case 'ts': return (0, i18n_1.t)('TypeScript 文件推测');
|
|
836129
|
+
case 'py': return (0, i18n_1.t)('Python 文件推测');
|
|
836130
|
+
case 'php': return (0, i18n_1.t)('PHP 文件推测');
|
|
836131
|
+
case 'java': return (0, i18n_1.t)('Java 文件推测');
|
|
836132
|
+
}
|
|
836133
|
+
}
|
|
836134
|
+
}
|
|
836135
|
+
catch (e) {
|
|
836136
|
+
}
|
|
836137
|
+
return (0, i18n_1.t)('默认配置');
|
|
835222
836138
|
}
|
|
835223
836139
|
doDeploySingleFunction(options) {
|
|
835224
836140
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835225
|
-
const { func, envId, force, codeSecret, access, deployMode, functionRootPath, functionPath, log } = options;
|
|
836141
|
+
const { func, envId, force, codeSecret, access, deployMode, functionRootPath, functionPath, yes, log, preCheckResult } = options;
|
|
835226
836142
|
if (func.type === 'HTTP') {
|
|
835227
836143
|
const funcPath = functionPath === '.' ? process.cwd() : (functionPath || path_1.default.join(functionRootPath, func.name));
|
|
835228
836144
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, func);
|
|
@@ -835256,7 +836172,9 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835256
836172
|
func,
|
|
835257
836173
|
accessPath: access,
|
|
835258
836174
|
functionPath,
|
|
835259
|
-
|
|
836175
|
+
yes,
|
|
836176
|
+
logger: log,
|
|
836177
|
+
preCheckResult
|
|
835260
836178
|
});
|
|
835261
836179
|
}
|
|
835262
836180
|
if (access || func.path) {
|
|
@@ -835267,7 +836185,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835267
836185
|
}
|
|
835268
836186
|
deployAllFunction(options) {
|
|
835269
836187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835270
|
-
let { functions = [], envId, force, codeSecret, functionRootPath, all, access, httpFn, ws, deployMode, log } = options;
|
|
836188
|
+
let { functions = [], envId, force, codeSecret, functionRootPath, all, access, httpFn, ws, deployMode, yes, log } = options;
|
|
835271
836189
|
if (!functions || functions.length === 0) {
|
|
835272
836190
|
functions = this.scanFunctionDirectory(functionRootPath, httpFn);
|
|
835273
836191
|
if (functions.length > 0) {
|
|
@@ -835284,7 +836202,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835284
836202
|
throw new error_1.CloudBaseError((0, i18n_1.t)('未找到云函数配置,请在 cloudbaserc.json 中配置 functions 字段,或使用 tcb fn deploy <函数名> 指定要部署的函数'));
|
|
835285
836203
|
}
|
|
835286
836204
|
let selectedFunctions = functions;
|
|
835287
|
-
if (!all) {
|
|
836205
|
+
if (!all && !yes) {
|
|
835288
836206
|
const choices = functions.map((func) => ({
|
|
835289
836207
|
name: `${func.name}${func.type === 'HTTP' ? ' (HTTP)' : ''}${func.protocolType === 'WS' ? ' (WS)' : ''}`,
|
|
835290
836208
|
value: func.name,
|
|
@@ -835317,7 +836235,60 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835317
836235
|
throw new error_1.CloudBaseError((0, i18n_1.t)('没有选择任何云函数'));
|
|
835318
836236
|
}
|
|
835319
836237
|
}
|
|
836238
|
+
else if (yes) {
|
|
836239
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:自动部署全部 {{count}} 个函数', { count: functions.length }));
|
|
836240
|
+
}
|
|
835320
836241
|
const loading = (0, utils_1.loadingFactory)();
|
|
836242
|
+
let functionsToOverwrite = new Set();
|
|
836243
|
+
if (!force && !yes) {
|
|
836244
|
+
loading.start((0, i18n_1.t)('正在检查云函数状态...'));
|
|
836245
|
+
const functionService = yield (0, function_2.getFunctionService)(envId);
|
|
836246
|
+
const existingFunctions = [];
|
|
836247
|
+
const checkTasks = selectedFunctions.map((func) => __awaiter(this, void 0, void 0, function* () {
|
|
836248
|
+
try {
|
|
836249
|
+
const detail = yield functionService.getFunctionDetail(func.name, codeSecret);
|
|
836250
|
+
if (detail) {
|
|
836251
|
+
return func.name;
|
|
836252
|
+
}
|
|
836253
|
+
}
|
|
836254
|
+
catch (e) {
|
|
836255
|
+
}
|
|
836256
|
+
return null;
|
|
836257
|
+
}));
|
|
836258
|
+
const checkResults = yield Promise.all(checkTasks);
|
|
836259
|
+
checkResults.forEach(name => {
|
|
836260
|
+
if (name)
|
|
836261
|
+
existingFunctions.push(name);
|
|
836262
|
+
});
|
|
836263
|
+
loading.stop();
|
|
836264
|
+
if (existingFunctions.length > 0) {
|
|
836265
|
+
log.info((0, i18n_1.t)('发现 {{count}} 个已存在的云函数:', { count: existingFunctions.length }));
|
|
836266
|
+
existingFunctions.forEach(name => {
|
|
836267
|
+
log.info(` - ${name}`);
|
|
836268
|
+
});
|
|
836269
|
+
const { toOverwrite } = yield inquirer_1.default.prompt({
|
|
836270
|
+
type: 'checkbox',
|
|
836271
|
+
name: 'toOverwrite',
|
|
836272
|
+
message: (0, i18n_1.t)('请选择要覆盖更新的函数(未选中的将跳过部署)'),
|
|
836273
|
+
choices: existingFunctions.map(name => ({
|
|
836274
|
+
name,
|
|
836275
|
+
value: name,
|
|
836276
|
+
checked: true
|
|
836277
|
+
}))
|
|
836278
|
+
});
|
|
836279
|
+
functionsToOverwrite = new Set(toOverwrite);
|
|
836280
|
+
const skippedByUser = existingFunctions.filter(name => !functionsToOverwrite.has(name));
|
|
836281
|
+
if (skippedByUser.length > 0) {
|
|
836282
|
+
log.info((0, i18n_1.t)('以下函数将跳过部署:{{names}}', { names: skippedByUser.join(', ') }));
|
|
836283
|
+
}
|
|
836284
|
+
}
|
|
836285
|
+
}
|
|
836286
|
+
else if (force) {
|
|
836287
|
+
log.verbose((0, i18n_1.t)('--force 模式:将自动覆盖所有已存在的函数'));
|
|
836288
|
+
}
|
|
836289
|
+
else if (yes) {
|
|
836290
|
+
log.verbose((0, i18n_1.t)('--yes 模式:将自动覆盖所有已存在的函数'));
|
|
836291
|
+
}
|
|
835321
836292
|
const tasks = selectedFunctions.map((func) => () => __awaiter(this, void 0, void 0, function* () {
|
|
835322
836293
|
let funcWithType = httpFn ? Object.assign(Object.assign({}, func), { type: 'HTTP' }) : func;
|
|
835323
836294
|
if (ws) {
|
|
@@ -835328,13 +836299,13 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835328
836299
|
: path_1.default.join(functionRootPath, func.name);
|
|
835329
836300
|
if (!fs_1.default.existsSync(funcPath)) {
|
|
835330
836301
|
log.error((0, i18n_1.t)('未找到函数 [{{name}}] 的目录:{{path}},已跳过', { name: func.name, path: funcPath }));
|
|
835331
|
-
return;
|
|
836302
|
+
return { status: 'skipped', name: func.name };
|
|
835332
836303
|
}
|
|
835333
836304
|
if (funcWithType.type === 'HTTP') {
|
|
835334
836305
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, funcWithType);
|
|
835335
836306
|
if (!shouldContinue) {
|
|
835336
836307
|
log.warn((0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }));
|
|
835337
|
-
return;
|
|
836308
|
+
return { status: 'skipped', name: func.name };
|
|
835338
836309
|
}
|
|
835339
836310
|
}
|
|
835340
836311
|
loading.start((0, i18n_1.t)('云函数部署中'));
|
|
@@ -835350,19 +836321,28 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835350
836321
|
deployMode
|
|
835351
836322
|
});
|
|
835352
836323
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数部署成功', { name: func.name }));
|
|
836324
|
+
return { status: 'success', name: func.name };
|
|
835353
836325
|
}
|
|
835354
836326
|
catch (e) {
|
|
835355
836327
|
loading.stop();
|
|
835356
|
-
|
|
835357
|
-
|
|
835358
|
-
|
|
835359
|
-
|
|
835360
|
-
|
|
835361
|
-
|
|
835362
|
-
|
|
835363
|
-
|
|
835364
|
-
|
|
835365
|
-
|
|
836328
|
+
try {
|
|
836329
|
+
const result = yield this.handleDeployFail(e, {
|
|
836330
|
+
func: funcWithType,
|
|
836331
|
+
envId,
|
|
836332
|
+
force,
|
|
836333
|
+
codeSecret,
|
|
836334
|
+
functionRootPath,
|
|
836335
|
+
functionPath: func.dir ? funcPath : undefined,
|
|
836336
|
+
accessPath: access,
|
|
836337
|
+
yes: yes || force || functionsToOverwrite.has(func.name),
|
|
836338
|
+
batchMode: true,
|
|
836339
|
+
logger: log
|
|
836340
|
+
});
|
|
836341
|
+
return { status: result || 'error', name: func.name };
|
|
836342
|
+
}
|
|
836343
|
+
catch (handleError) {
|
|
836344
|
+
return { status: 'error', name: func.name, error: handleError };
|
|
836345
|
+
}
|
|
835366
836346
|
}
|
|
835367
836347
|
}));
|
|
835368
836348
|
if (tasks.length > 5) {
|
|
@@ -835370,51 +836350,111 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835370
836350
|
}
|
|
835371
836351
|
const asyncTaskController = new utils_1.AsyncTaskParallelController(5, 50);
|
|
835372
836352
|
asyncTaskController.loadTasks(tasks);
|
|
835373
|
-
const
|
|
835374
|
-
const
|
|
835375
|
-
|
|
835376
|
-
|
|
835377
|
-
|
|
835378
|
-
|
|
835379
|
-
|
|
835380
|
-
|
|
835381
|
-
|
|
836353
|
+
const rawResults = yield asyncTaskController.run();
|
|
836354
|
+
const results = rawResults.map((r, index) => {
|
|
836355
|
+
var _a;
|
|
836356
|
+
if (r instanceof Error) {
|
|
836357
|
+
return { status: 'error', name: ((_a = selectedFunctions[index]) === null || _a === void 0 ? void 0 : _a.name) || 'unknown', error: r };
|
|
836358
|
+
}
|
|
836359
|
+
return r;
|
|
836360
|
+
});
|
|
836361
|
+
const successCount = results.filter(r => (r === null || r === void 0 ? void 0 : r.status) === 'success').length;
|
|
836362
|
+
const skippedCount = results.filter(r => (r === null || r === void 0 ? void 0 : r.status) === 'skipped').length;
|
|
836363
|
+
const cancelledCount = results.filter(r => (r === null || r === void 0 ? void 0 : r.status) === 'cancelled').length;
|
|
836364
|
+
const errorCount = results.filter(r => (r === null || r === void 0 ? void 0 : r.status) === 'error').length;
|
|
836365
|
+
if (successCount > 0) {
|
|
836366
|
+
log.success((0, i18n_1.t)('成功部署 {{count}} 个函数', { count: successCount }));
|
|
836367
|
+
}
|
|
836368
|
+
if (skippedCount > 0) {
|
|
836369
|
+
log.warn((0, i18n_1.t)('跳过 {{count}} 个函数', { count: skippedCount }));
|
|
836370
|
+
}
|
|
836371
|
+
if (cancelledCount > 0) {
|
|
836372
|
+
log.info((0, i18n_1.t)('取消部署 {{count}} 个函数', { count: cancelledCount }));
|
|
836373
|
+
}
|
|
836374
|
+
if (errorCount > 0) {
|
|
836375
|
+
log.error((0, i18n_1.t)('{{count}} 个云函数部署失败', { count: errorCount }));
|
|
836376
|
+
let envNotFoundError = null;
|
|
836377
|
+
const stackIgnoreErrors = ['TencentCloudSDKHttpException', 'CloudBaseError'];
|
|
836378
|
+
results.filter(r => (r === null || r === void 0 ? void 0 : r.status) === 'error').forEach((r) => {
|
|
836379
|
+
var _a, _b;
|
|
836380
|
+
if (r === null || r === void 0 ? void 0 : r.error) {
|
|
836381
|
+
const err = r.error;
|
|
836382
|
+
log.error(` - [${r.name}] ${err.message || err}`);
|
|
836383
|
+
if (err.requestId) {
|
|
836384
|
+
log.error(` requestId: ${err.requestId}`);
|
|
836385
|
+
}
|
|
836386
|
+
if (err.stack && !stackIgnoreErrors.includes(err.name)) {
|
|
836387
|
+
const stackLines = err.stack.split('\n').slice(1, 6);
|
|
836388
|
+
stackLines.forEach(line => log.error(` ${line.trim()}`));
|
|
836389
|
+
}
|
|
836390
|
+
if (((_a = err.message) === null || _a === void 0 ? void 0 : _a.includes('Environment')) && ((_b = err.message) === null || _b === void 0 ? void 0 : _b.includes('not found')) && !envNotFoundError) {
|
|
836391
|
+
envNotFoundError = err;
|
|
836392
|
+
}
|
|
835382
836393
|
}
|
|
835383
836394
|
});
|
|
836395
|
+
if (envNotFoundError) {
|
|
836396
|
+
throw envNotFoundError;
|
|
836397
|
+
}
|
|
836398
|
+
}
|
|
836399
|
+
if (successCount === 0 && errorCount === 0 && skippedCount === 0 && cancelledCount === 0) {
|
|
836400
|
+
log.info((0, i18n_1.t)('没有函数被部署'));
|
|
835384
836401
|
}
|
|
835385
836402
|
});
|
|
835386
836403
|
}
|
|
835387
836404
|
handleDeployFail(e, options) {
|
|
836405
|
+
var _a;
|
|
835388
836406
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835389
|
-
const { envId, codeSecret, functionRootPath, func: originalFunc, functionPath, accessPath, force: forceOverwrite, logger: log } = options;
|
|
836407
|
+
const { envId, codeSecret, functionRootPath, func: originalFunc, functionPath, accessPath, force: forceOverwrite, yes, batchMode, logger: log, preCheckResult } = options;
|
|
835390
836408
|
let func = originalFunc;
|
|
835391
836409
|
const loading = (0, utils_1.loadingFactory)();
|
|
835392
|
-
|
|
835393
|
-
|
|
835394
|
-
|
|
835395
|
-
|
|
835396
|
-
|
|
835397
|
-
|
|
835398
|
-
|
|
835399
|
-
|
|
835400
|
-
|
|
835401
|
-
|
|
835402
|
-
|
|
835403
|
-
|
|
836410
|
+
const isResourceInUseError = e.code === 'ResourceInUse.FunctionName'
|
|
836411
|
+
|| e.code === 'ResourceInUse.Function'
|
|
836412
|
+
|| (e.message && e.message.includes('ResourceInUse.FunctionName'))
|
|
836413
|
+
|| (e.message && e.message.includes('ResourceInUse.Function'));
|
|
836414
|
+
if (!isResourceInUseError) {
|
|
836415
|
+
this.displayFriendlyError(e, {
|
|
836416
|
+
functionName: func.name,
|
|
836417
|
+
operation: '函数部署'
|
|
836418
|
+
}, log);
|
|
836419
|
+
return 'error';
|
|
836420
|
+
}
|
|
836421
|
+
if (isResourceInUseError) {
|
|
836422
|
+
let existingFunction;
|
|
836423
|
+
if (preCheckResult && preCheckResult.exists && preCheckResult.functionDetail) {
|
|
836424
|
+
existingFunction = preCheckResult.functionDetail;
|
|
836425
|
+
(_a = log === null || log === void 0 ? void 0 : log.verbose) === null || _a === void 0 ? void 0 : _a.call(log, (0, i18n_1.t)('复用前置检测结果,避免重复 API 调用'));
|
|
835404
836426
|
}
|
|
836427
|
+
else {
|
|
836428
|
+
try {
|
|
836429
|
+
const functionService = yield (0, function_2.getFunctionService)(envId);
|
|
836430
|
+
existingFunction = (yield functionService.getFunctionDetail(func.name, codeSecret));
|
|
836431
|
+
}
|
|
836432
|
+
catch (detailError) {
|
|
836433
|
+
this.displayFriendlyError(detailError, {
|
|
836434
|
+
functionName: func.name,
|
|
836435
|
+
operation: '获取函数详情'
|
|
836436
|
+
}, log);
|
|
836437
|
+
return 'error';
|
|
836438
|
+
}
|
|
836439
|
+
}
|
|
836440
|
+
const conflicts = this.detectConfigConflicts(func, existingFunction);
|
|
836441
|
+
if (conflicts.length > 0) {
|
|
836442
|
+
this.displayConfigConflicts(func.name, conflicts);
|
|
836443
|
+
return 'error';
|
|
836444
|
+
}
|
|
836445
|
+
func = this.mergeCloudAndLocalConfig(existingFunction, func);
|
|
836446
|
+
const existingType = (existingFunction === null || existingFunction === void 0 ? void 0 : existingFunction.Type) || 'Event';
|
|
835405
836447
|
const existingProtocolType = (existingFunction === null || existingFunction === void 0 ? void 0 : existingFunction.ProtocolType) || '';
|
|
835406
|
-
const
|
|
835407
|
-
|
|
835408
|
-
|
|
835409
|
-
|
|
835410
|
-
|
|
835411
|
-
|
|
835412
|
-
}));
|
|
835413
|
-
return;
|
|
836448
|
+
const localTypeDisplay = originalFunc.type || (0, i18n_1.t)('未指定');
|
|
836449
|
+
const cloudTypeDisplay = existingType === 'HTTP' ? 'HTTP' : 'Event';
|
|
836450
|
+
if (!originalFunc.type && existingType) {
|
|
836451
|
+
(log || utils_1.logger).info((0, i18n_1.t)('ℹ 本地配置未指定函数类型,将保持云端类型:{{cloudType}}', { cloudType: cloudTypeDisplay }));
|
|
836452
|
+
}
|
|
836453
|
+
if (!originalFunc.protocolType && existingProtocolType) {
|
|
836454
|
+
(log || utils_1.logger).info((0, i18n_1.t)('ℹ 本地配置未指定协议类型,将保持云端协议:{{protocolType}}', { protocolType: existingProtocolType }));
|
|
835414
836455
|
}
|
|
835415
|
-
|
|
835416
|
-
|
|
835417
|
-
if (!shouldForce) {
|
|
836456
|
+
let shouldForce = forceOverwrite || yes;
|
|
836457
|
+
if (!shouldForce && !batchMode) {
|
|
835418
836458
|
const answer = yield inquirer_1.default.prompt({
|
|
835419
836459
|
type: 'confirm',
|
|
835420
836460
|
name: 'force',
|
|
@@ -835423,9 +836463,12 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835423
836463
|
});
|
|
835424
836464
|
shouldForce = answer.force;
|
|
835425
836465
|
}
|
|
835426
|
-
|
|
836466
|
+
else if (!shouldForce && batchMode) {
|
|
836467
|
+
(log || utils_1.logger).info((0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }));
|
|
836468
|
+
return 'cancelled';
|
|
836469
|
+
}
|
|
835427
836470
|
if (shouldForce) {
|
|
835428
|
-
loading.start((0, i18n_1.t)('云函数更新部署中...'));
|
|
836471
|
+
loading.start(batchMode ? (0, i18n_1.t)('云函数 [{{name}}] 更新部署中...', { name: func.name }) : (0, i18n_1.t)('云函数更新部署中...'));
|
|
835429
836472
|
try {
|
|
835430
836473
|
yield (0, function_2.updateFunctionCode)({
|
|
835431
836474
|
func,
|
|
@@ -835436,7 +836479,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835436
836479
|
});
|
|
835437
836480
|
const success = yield this.waitForFunctionReady(envId, func.name, loading);
|
|
835438
836481
|
if (!success) {
|
|
835439
|
-
return;
|
|
836482
|
+
return 'error';
|
|
835440
836483
|
}
|
|
835441
836484
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数配置更新中...', { name: func.name }));
|
|
835442
836485
|
yield (0, function_2.updateFunctionConfig)({
|
|
@@ -835445,7 +836488,10 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835445
836488
|
config: func
|
|
835446
836489
|
});
|
|
835447
836490
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数更新成功!', { name: func.name }));
|
|
835448
|
-
|
|
836491
|
+
if (!batchMode) {
|
|
836492
|
+
yield this.printSuccessTips(envId);
|
|
836493
|
+
}
|
|
836494
|
+
return 'success';
|
|
835449
836495
|
}
|
|
835450
836496
|
catch (e) {
|
|
835451
836497
|
loading.stop();
|
|
@@ -835453,9 +836499,9 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835453
836499
|
}
|
|
835454
836500
|
}
|
|
835455
836501
|
else {
|
|
835456
|
-
(log || utils_1.logger).info((0, i18n_1.t)('已取消部署'));
|
|
836502
|
+
(log || utils_1.logger).info(batchMode ? (0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }) : (0, i18n_1.t)('已取消部署'));
|
|
836503
|
+
return 'cancelled';
|
|
835457
836504
|
}
|
|
835458
|
-
return;
|
|
835459
836505
|
}
|
|
835460
836506
|
throw e;
|
|
835461
836507
|
});
|
|
@@ -835573,6 +836619,284 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835573
836619
|
return runtime;
|
|
835574
836620
|
});
|
|
835575
836621
|
}
|
|
836622
|
+
getDefaultRuntime(targetDir) {
|
|
836623
|
+
var _a;
|
|
836624
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836625
|
+
const dir = targetDir || process.cwd();
|
|
836626
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, 'package.json'))) {
|
|
836627
|
+
try {
|
|
836628
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, 'package.json'), 'utf-8'));
|
|
836629
|
+
if ((_a = packageJson.engines) === null || _a === void 0 ? void 0 : _a.node) {
|
|
836630
|
+
const nodeVersion = packageJson.engines.node;
|
|
836631
|
+
if (nodeVersion.includes('20'))
|
|
836632
|
+
return 'Nodejs20.19';
|
|
836633
|
+
if (nodeVersion.includes('16'))
|
|
836634
|
+
return 'Nodejs16.13';
|
|
836635
|
+
}
|
|
836636
|
+
}
|
|
836637
|
+
catch (e) {
|
|
836638
|
+
}
|
|
836639
|
+
return constant_1.DefaultFunctionDeployConfig.runtime;
|
|
836640
|
+
}
|
|
836641
|
+
const pythonFiles = ['requirements.txt', 'setup.py', 'pyproject.toml'];
|
|
836642
|
+
if (pythonFiles.some(file => fs_1.default.existsSync(path_1.default.join(dir, file)))) {
|
|
836643
|
+
return 'Python3.9';
|
|
836644
|
+
}
|
|
836645
|
+
if (fs_1.default.existsSync(path_1.default.join(dir, 'composer.json')) ||
|
|
836646
|
+
fs_1.default.readdirSync(dir).some(file => file.endsWith('.php'))) {
|
|
836647
|
+
return 'Php8.0';
|
|
836648
|
+
}
|
|
836649
|
+
const javaFiles = ['pom.xml', 'build.gradle', 'build.gradle.kts'];
|
|
836650
|
+
if (javaFiles.some(file => fs_1.default.existsSync(path_1.default.join(dir, file)))) {
|
|
836651
|
+
return 'Java11';
|
|
836652
|
+
}
|
|
836653
|
+
try {
|
|
836654
|
+
const files = fs_1.default.readdirSync(dir);
|
|
836655
|
+
const fileTypes = {
|
|
836656
|
+
js: files.filter(f => f.endsWith('.js')).length,
|
|
836657
|
+
ts: files.filter(f => f.endsWith('.ts')).length,
|
|
836658
|
+
py: files.filter(f => f.endsWith('.py')).length,
|
|
836659
|
+
php: files.filter(f => f.endsWith('.php')).length,
|
|
836660
|
+
java: files.filter(f => f.endsWith('.java')).length
|
|
836661
|
+
};
|
|
836662
|
+
const maxType = Object.entries(fileTypes).reduce((a, b) => fileTypes[a[0]] > fileTypes[b[0]] ? a : b);
|
|
836663
|
+
switch (maxType[0]) {
|
|
836664
|
+
case 'py': return 'Python3.9';
|
|
836665
|
+
case 'php': return 'Php8.0';
|
|
836666
|
+
case 'java': return 'Java11';
|
|
836667
|
+
default: return constant_1.DefaultFunctionDeployConfig.runtime;
|
|
836668
|
+
}
|
|
836669
|
+
}
|
|
836670
|
+
catch (e) {
|
|
836671
|
+
return constant_1.DefaultFunctionDeployConfig.runtime;
|
|
836672
|
+
}
|
|
836673
|
+
});
|
|
836674
|
+
}
|
|
836675
|
+
checkCloudFunction(functionName, envId, codeSecret) {
|
|
836676
|
+
var _a, _b;
|
|
836677
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836678
|
+
try {
|
|
836679
|
+
const functionService = yield (0, function_2.getFunctionService)(envId);
|
|
836680
|
+
const detail = yield functionService.getFunctionDetail(functionName, codeSecret);
|
|
836681
|
+
return {
|
|
836682
|
+
exists: true,
|
|
836683
|
+
functionDetail: detail,
|
|
836684
|
+
checkTime: Date.now(),
|
|
836685
|
+
uncertain: false
|
|
836686
|
+
};
|
|
836687
|
+
}
|
|
836688
|
+
catch (error) {
|
|
836689
|
+
if (error.code === 'ResourceNotFound.Function' ||
|
|
836690
|
+
error.code === 'ResourceNotFound' ||
|
|
836691
|
+
((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('does not exist')) ||
|
|
836692
|
+
((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('not found'))) {
|
|
836693
|
+
return { exists: false, uncertain: false };
|
|
836694
|
+
}
|
|
836695
|
+
if (error.code === 'ENOTFOUND' || error.code === 'ECONNRESET' ||
|
|
836696
|
+
error.code === 'ETIMEDOUT' || error.code === 'NetworkError' ||
|
|
836697
|
+
error.code === 'Forbidden' || error.code === 'Unauthorized' ||
|
|
836698
|
+
error.code === 'AuthFailure' || error.code === 'UnauthorizedOperation') {
|
|
836699
|
+
return { exists: false, uncertain: true, error };
|
|
836700
|
+
}
|
|
836701
|
+
throw error;
|
|
836702
|
+
}
|
|
836703
|
+
});
|
|
836704
|
+
}
|
|
836705
|
+
checkBatchFunctions(functionNames, envId, codeSecret) {
|
|
836706
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836707
|
+
const checkTasks = functionNames.map((name) => __awaiter(this, void 0, void 0, function* () {
|
|
836708
|
+
try {
|
|
836709
|
+
const result = yield this.checkCloudFunction(name, envId, codeSecret);
|
|
836710
|
+
return Object.assign({ name }, result);
|
|
836711
|
+
}
|
|
836712
|
+
catch (error) {
|
|
836713
|
+
return {
|
|
836714
|
+
name,
|
|
836715
|
+
exists: false,
|
|
836716
|
+
uncertain: true,
|
|
836717
|
+
error
|
|
836718
|
+
};
|
|
836719
|
+
}
|
|
836720
|
+
}));
|
|
836721
|
+
const results = yield Promise.all(checkTasks);
|
|
836722
|
+
const existing = results.filter((r) => r.exists).map((r) => ({
|
|
836723
|
+
name: r.name,
|
|
836724
|
+
detail: r.functionDetail
|
|
836725
|
+
}));
|
|
836726
|
+
const missing = results.filter((r) => !r.exists && !r.uncertain).map((r) => ({
|
|
836727
|
+
name: r.name
|
|
836728
|
+
}));
|
|
836729
|
+
const uncertain = results.filter((r) => r.uncertain).map((r) => ({
|
|
836730
|
+
name: r.name,
|
|
836731
|
+
error: r.error
|
|
836732
|
+
}));
|
|
836733
|
+
return { existing, missing, uncertain, totalChecked: results.length };
|
|
836734
|
+
});
|
|
836735
|
+
}
|
|
836736
|
+
detectConfigConflicts(localConfig, cloudConfig) {
|
|
836737
|
+
const conflicts = [];
|
|
836738
|
+
const immutableFields = [
|
|
836739
|
+
{ local: 'type', cloud: 'Type', name: '函数类型' },
|
|
836740
|
+
{ local: 'protocolType', cloud: 'ProtocolType', name: '协议类型' }
|
|
836741
|
+
];
|
|
836742
|
+
immutableFields.forEach(field => {
|
|
836743
|
+
const localValue = localConfig[field.local];
|
|
836744
|
+
const cloudValue = cloudConfig[field.cloud];
|
|
836745
|
+
if (localValue && cloudValue && localValue !== cloudValue) {
|
|
836746
|
+
conflicts.push({
|
|
836747
|
+
field: field.name,
|
|
836748
|
+
localValue,
|
|
836749
|
+
cloudValue,
|
|
836750
|
+
severity: 'error',
|
|
836751
|
+
message: `${field.name}不匹配,无法更新`
|
|
836752
|
+
});
|
|
836753
|
+
}
|
|
836754
|
+
});
|
|
836755
|
+
return conflicts;
|
|
836756
|
+
}
|
|
836757
|
+
mergeCloudAndLocalConfig(cloudFunction, localConfig) {
|
|
836758
|
+
return Object.assign(Object.assign({}, localConfig), { type: cloudFunction.Type || localConfig.type, protocolType: cloudFunction.ProtocolType || localConfig.protocolType });
|
|
836759
|
+
}
|
|
836760
|
+
checkDirectoryExists(functionPath) {
|
|
836761
|
+
return fs_1.default.existsSync(functionPath) && fs_1.default.statSync(functionPath).isDirectory();
|
|
836762
|
+
}
|
|
836763
|
+
displayFriendlyError(error, context = {}, log) {
|
|
836764
|
+
const logger = log || (__webpack_require__(82079).logger);
|
|
836765
|
+
const { functionName, operation = '操作' } = context;
|
|
836766
|
+
const errorPrefix = functionName ? `[${functionName}] ` : '';
|
|
836767
|
+
logger.error(`${errorPrefix}${operation}失败`);
|
|
836768
|
+
if (error.message) {
|
|
836769
|
+
logger.error(` 错误信息: ${error.message}`);
|
|
836770
|
+
}
|
|
836771
|
+
if (error.code) {
|
|
836772
|
+
logger.error(` 错误码: ${error.code}`);
|
|
836773
|
+
}
|
|
836774
|
+
if (error.requestId) {
|
|
836775
|
+
logger.error(` RequestId: ${error.requestId}`);
|
|
836776
|
+
}
|
|
836777
|
+
const suggestions = this.getSpecificSuggestions(error, context);
|
|
836778
|
+
if (suggestions.length > 0) {
|
|
836779
|
+
logger.info((0, i18n_1.t)('解决建议:'));
|
|
836780
|
+
suggestions.forEach((suggestion, index) => {
|
|
836781
|
+
logger.info(` ${index + 1}. ${suggestion}`);
|
|
836782
|
+
});
|
|
836783
|
+
}
|
|
836784
|
+
}
|
|
836785
|
+
getSpecificSuggestions(error, context = {}) {
|
|
836786
|
+
const { functionName } = context;
|
|
836787
|
+
if (error.code === 'Forbidden' || error.code === 'Unauthorized' ||
|
|
836788
|
+
error.code === 'AuthFailure' || error.code === 'UnauthorizedOperation') {
|
|
836789
|
+
return [
|
|
836790
|
+
(0, i18n_1.t)('运行 {{command}} 重新登录', { command: (0, utils_1.highlightCommand)('tcb login') }),
|
|
836791
|
+
(0, i18n_1.t)('检查当前账号是否有该环境的操作权限'),
|
|
836792
|
+
];
|
|
836793
|
+
}
|
|
836794
|
+
if (error.code === 'ResourceNotFound' || error.code === 'ResourceNotFound.FunctionName') {
|
|
836795
|
+
return [
|
|
836796
|
+
(0, i18n_1.t)('检查函数名称是否正确'),
|
|
836797
|
+
(0, i18n_1.t)('检查环境ID是否正确'),
|
|
836798
|
+
];
|
|
836799
|
+
}
|
|
836800
|
+
if (error.code === 'InvalidParameter' || error.code === 'InvalidParameterValue') {
|
|
836801
|
+
return [
|
|
836802
|
+
(0, i18n_1.t)('检查函数配置参数是否在允许范围内(如内存、超时时间等)'),
|
|
836803
|
+
(0, i18n_1.t)('参考文档: https://cloud.tencent.com/document/product/876/19358'),
|
|
836804
|
+
];
|
|
836805
|
+
}
|
|
836806
|
+
if (error.code === 'LimitExceeded') {
|
|
836807
|
+
return [
|
|
836808
|
+
(0, i18n_1.t)('当前环境函数数量已达上限'),
|
|
836809
|
+
(0, i18n_1.t)('删除不需要的函数或升级套餐'),
|
|
836810
|
+
];
|
|
836811
|
+
}
|
|
836812
|
+
if (error.code === 'ResourceInUse.FunctionName' || error.code === 'ResourceInUse.Function') {
|
|
836813
|
+
return [
|
|
836814
|
+
(0, i18n_1.t)('函数已存在,使用 -f 参数强制覆盖'),
|
|
836815
|
+
];
|
|
836816
|
+
}
|
|
836817
|
+
if (error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT' ||
|
|
836818
|
+
error.code === 'ENOTFOUND' || error.code === 'NetworkError') {
|
|
836819
|
+
return [
|
|
836820
|
+
(0, i18n_1.t)('检查网络连接是否正常'),
|
|
836821
|
+
(0, i18n_1.t)('检查是否需要配置代理'),
|
|
836822
|
+
];
|
|
836823
|
+
}
|
|
836824
|
+
return [];
|
|
836825
|
+
}
|
|
836826
|
+
handleBatchErrors(errors, log) {
|
|
836827
|
+
if (errors.length === 0)
|
|
836828
|
+
return;
|
|
836829
|
+
log.error((0, i18n_1.t)('以下函数操作失败:'));
|
|
836830
|
+
errors.forEach(({ functionName, error, operation = '部署' }) => {
|
|
836831
|
+
log.error(` ✗ [${functionName}] ${operation}失败`);
|
|
836832
|
+
if (error.message) {
|
|
836833
|
+
log.error(` 错误信息: ${error.message}`);
|
|
836834
|
+
}
|
|
836835
|
+
if (error.code) {
|
|
836836
|
+
log.error(` 错误码: ${error.code}`);
|
|
836837
|
+
}
|
|
836838
|
+
if (error.requestId) {
|
|
836839
|
+
log.error(` RequestId: ${error.requestId}`);
|
|
836840
|
+
}
|
|
836841
|
+
const suggestions = this.getSpecificSuggestions(error, { functionName, operation });
|
|
836842
|
+
if (suggestions.length > 0) {
|
|
836843
|
+
suggestions.forEach((suggestion) => {
|
|
836844
|
+
log.info(` - ${suggestion}`);
|
|
836845
|
+
});
|
|
836846
|
+
}
|
|
836847
|
+
});
|
|
836848
|
+
}
|
|
836849
|
+
displayConfigConflicts(functionName, conflicts) {
|
|
836850
|
+
utils_1.logger.error((0, i18n_1.t)('函数 [{{name}}] 存在配置冲突:', { name: functionName }));
|
|
836851
|
+
conflicts.forEach((conflict) => {
|
|
836852
|
+
utils_1.logger.error(` ✗ ${conflict.field}: 云端 ${conflict.cloudValue} ≠ 本地 ${conflict.localValue}`);
|
|
836853
|
+
utils_1.logger.error(` ${conflict.message}`);
|
|
836854
|
+
});
|
|
836855
|
+
utils_1.logger.info((0, i18n_1.t)('解决建议:'));
|
|
836856
|
+
utils_1.logger.info((0, i18n_1.t)(' 1. 修改本地配置使其与云端一致'));
|
|
836857
|
+
utils_1.logger.info((0, i18n_1.t)(' 2. 删除云端函数后重新创建'));
|
|
836858
|
+
utils_1.logger.info((0, i18n_1.t)(' 3. 使用 {{command}} 查看云端配置', {
|
|
836859
|
+
command: (0, utils_1.highlightCommand)(`tcb fn detail ${functionName}`)
|
|
836860
|
+
}));
|
|
836861
|
+
}
|
|
836862
|
+
displayMergedConfig(functionName, config, source) {
|
|
836863
|
+
utils_1.logger.info((0, i18n_1.t)('函数 [{{name}}] 最终配置:', { name: functionName }));
|
|
836864
|
+
utils_1.logger.info(` ${(0, i18n_1.t)('类型')}: ${config.type || 'Event'}`);
|
|
836865
|
+
utils_1.logger.info(` ${(0, i18n_1.t)('运行时')}: ${config.runtime}`);
|
|
836866
|
+
utils_1.logger.info(` ${(0, i18n_1.t)('入口')}: ${config.handler}`);
|
|
836867
|
+
if (config.memorySize) {
|
|
836868
|
+
utils_1.logger.info(` ${(0, i18n_1.t)('内存')}: ${config.memorySize}MB`);
|
|
836869
|
+
}
|
|
836870
|
+
utils_1.logger.info(` ${(0, i18n_1.t)('超时')}: ${config.timeout}s`);
|
|
836871
|
+
if (source === 'inferred') {
|
|
836872
|
+
utils_1.logger.info((0, i18n_1.t)(' (配置来源: 智能推测)'));
|
|
836873
|
+
}
|
|
836874
|
+
else if (source === 'default') {
|
|
836875
|
+
utils_1.logger.info((0, i18n_1.t)(' (配置来源: 默认配置)'));
|
|
836876
|
+
}
|
|
836877
|
+
}
|
|
836878
|
+
confirmUpdate(functionName) {
|
|
836879
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836880
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
|
836881
|
+
type: 'confirm',
|
|
836882
|
+
name: 'confirm',
|
|
836883
|
+
message: (0, i18n_1.t)('检测到云端已存在函数 [{{name}}],是否覆盖更新?', { name: functionName }),
|
|
836884
|
+
default: false
|
|
836885
|
+
});
|
|
836886
|
+
return confirm;
|
|
836887
|
+
});
|
|
836888
|
+
}
|
|
836889
|
+
confirmDeploy() {
|
|
836890
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836891
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
|
836892
|
+
type: 'confirm',
|
|
836893
|
+
name: 'confirm',
|
|
836894
|
+
message: (0, i18n_1.t)('确认部署?'),
|
|
836895
|
+
default: true
|
|
836896
|
+
});
|
|
836897
|
+
return confirm;
|
|
836898
|
+
});
|
|
836899
|
+
}
|
|
835576
836900
|
};
|
|
835577
836901
|
__decorate([
|
|
835578
836902
|
(0, decorators_1.InjectParams)(),
|