@cloudbase/cli 2.12.3 → 2.12.4
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 +1508 -182
- 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","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
|
|
|
@@ -459815,7 +459815,7 @@ let FunctionDetail = class FunctionDetail extends common_1.Command {
|
|
|
459815
459815
|
this.logDetail(data, name);
|
|
459816
459816
|
}
|
|
459817
459817
|
catch (e) {
|
|
459818
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
459818
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
459819
459819
|
throw new error_1.CloudBaseError((0, i18n_1.t)('[{{name}}] 函数不存在', { name }));
|
|
459820
459820
|
}
|
|
459821
459821
|
throw e;
|
|
@@ -467694,12 +467694,15 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467694
467694
|
functionDetail = yield functionService.getFunctionDetail(name, codeSecret);
|
|
467695
467695
|
}
|
|
467696
467696
|
catch (e) {
|
|
467697
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
467697
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
467698
467698
|
throw new error_1.CloudBaseError((0, i18n_1.t)('云函数 [{{name}}] 不存在,请先使用 tcb fn deploy {{name}} 部署函数', { name }));
|
|
467699
467699
|
}
|
|
467700
467700
|
throw e;
|
|
467701
467701
|
}
|
|
467702
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;
|
|
467703
467706
|
if (!func.type) {
|
|
467704
467707
|
func.type = cloudFunctionType;
|
|
467705
467708
|
}
|
|
@@ -467710,6 +467713,16 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467710
467713
|
localType: func.type
|
|
467711
467714
|
}));
|
|
467712
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
|
+
}
|
|
467713
467726
|
if (cloudFunctionType === 'HTTP') {
|
|
467714
467727
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, Object.assign(Object.assign({}, func), { type: 'HTTP', runtime: functionDetail.Runtime }), {
|
|
467715
467728
|
cancelMessage: (0, i18n_1.t)('已取消更新,请手动创建 scf_bootstrap 文件后重试'),
|
|
@@ -467751,7 +467764,7 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
|
|
|
467751
467764
|
const mainFile = path_1.default.basename(packageJson.main).replace(/\.[^.]+$/, '');
|
|
467752
467765
|
handler = `${mainFile}.main`;
|
|
467753
467766
|
}
|
|
467754
|
-
return Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { handler });
|
|
467767
|
+
return Object.assign(Object.assign({ name }, constant_1.DefaultFunctionDeployConfig), { handler, installDependency: true });
|
|
467755
467768
|
}
|
|
467756
467769
|
catch (e) {
|
|
467757
467770
|
return null;
|
|
@@ -467891,11 +467904,11 @@ let CodeDownload = class CodeDownload extends common_1.Command {
|
|
|
467891
467904
|
yield functionService.getFunctionDetail(name, codeSecret);
|
|
467892
467905
|
}
|
|
467893
467906
|
catch (e) {
|
|
467894
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
467907
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
467895
467908
|
throw new error_1.CloudBaseError((0, i18n_1.t)('云函数 [{{name}}] 不存在!\n\n使用 {{command}} 命令查看已部署云函数', {
|
|
467896
467909
|
name,
|
|
467897
|
-
command: (0, utils_1.highlightCommand)('
|
|
467898
|
-
}));
|
|
467910
|
+
command: (0, utils_1.highlightCommand)('tcb fn list')
|
|
467911
|
+
}), e);
|
|
467899
467912
|
}
|
|
467900
467913
|
return;
|
|
467901
467914
|
}
|
|
@@ -493882,7 +493895,7 @@ function validateFunctionTypeChange(envId, func, log) {
|
|
|
493882
493895
|
existingFunction = yield functionService.getFunctionDetail(func.name);
|
|
493883
493896
|
}
|
|
493884
493897
|
catch (e) {
|
|
493885
|
-
if (e.code === 'ResourceNotFound.FunctionName') {
|
|
493898
|
+
if (e.code === 'ResourceNotFound.FunctionName' || e.code === 'ResourceNotFound.Function') {
|
|
493886
493899
|
log.error((0, i18n_1.t)('云函数 [{{name}}] 不存在,请先部署函数', { name: func.name }));
|
|
493887
493900
|
return false;
|
|
493888
493901
|
}
|
|
@@ -493925,6 +493938,10 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493925
493938
|
{
|
|
493926
493939
|
flags: '-e, --envId <envId>',
|
|
493927
493940
|
desc: (0, i18n_1.t)('环境 Id')
|
|
493941
|
+
},
|
|
493942
|
+
{
|
|
493943
|
+
flags: '--yes',
|
|
493944
|
+
desc: (0, i18n_1.t)('跳过交互确认,使用默认选项自动执行')
|
|
493928
493945
|
}
|
|
493929
493946
|
],
|
|
493930
493947
|
desc: (0, i18n_1.t)('更新云函数配置'),
|
|
@@ -493934,26 +493951,35 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493934
493951
|
}
|
|
493935
493952
|
execute(ctx, params, log) {
|
|
493936
493953
|
return __awaiter(this, void 0, void 0, function* () {
|
|
493937
|
-
let { envId, config: { functions } } = ctx;
|
|
493954
|
+
let { envId, config: { functions }, options } = ctx;
|
|
493938
493955
|
const name = params === null || params === void 0 ? void 0 : params[0];
|
|
493956
|
+
const { yes } = options;
|
|
493939
493957
|
let isBathUpdate = false;
|
|
493940
493958
|
if (!envId) {
|
|
493941
493959
|
envId = yield (0, utils_1.selectEnv)({ envTypes: [constant_1.EnvType.BAAS, constant_1.EnvType.WEDA] });
|
|
493942
493960
|
}
|
|
493943
493961
|
if (!name) {
|
|
493944
|
-
|
|
493945
|
-
|
|
493946
|
-
|
|
493947
|
-
|
|
493948
|
-
|
|
493949
|
-
|
|
493950
|
-
|
|
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
|
+
}
|
|
493951
493975
|
if (!isBathUpdate) {
|
|
493952
493976
|
throw new error_1.CloudBaseError((0, i18n_1.t)('请指定云函数名称!'));
|
|
493953
493977
|
}
|
|
493954
493978
|
}
|
|
493955
493979
|
if (isBathUpdate) {
|
|
493956
|
-
const envVarUpdateMode = hasEnvVariablesConfig(functions)
|
|
493980
|
+
const envVarUpdateMode = hasEnvVariablesConfig(functions)
|
|
493981
|
+
? (yes ? 'overwrite' : yield askEnvVarUpdateMode())
|
|
493982
|
+
: undefined;
|
|
493957
493983
|
for (const func of functions) {
|
|
493958
493984
|
const isValid = yield validateFunctionTypeChange(envId, func, log);
|
|
493959
493985
|
if (!isValid) {
|
|
@@ -493977,7 +494003,9 @@ let ConfigUpdate = class ConfigUpdate extends common_1.Command {
|
|
|
493977
494003
|
if (!isValid) {
|
|
493978
494004
|
return;
|
|
493979
494005
|
}
|
|
493980
|
-
const envVarUpdateMode = hasEnvVariablesConfig([functionItem])
|
|
494006
|
+
const envVarUpdateMode = hasEnvVariablesConfig([functionItem])
|
|
494007
|
+
? (yes ? 'overwrite' : yield askEnvVarUpdateMode())
|
|
494008
|
+
: undefined;
|
|
493981
494009
|
yield (0, function_1.updateFunctionConfig)({
|
|
493982
494010
|
envId,
|
|
493983
494011
|
functionName: name,
|
|
@@ -672188,6 +672216,547 @@ module.exports = function (value) {
|
|
|
672188
672216
|
};
|
|
672189
672217
|
|
|
672190
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
|
+
|
|
672191
672760
|
/***/ }),
|
|
672192
672761
|
|
|
672193
672762
|
/***/ 62629:
|
|
@@ -674063,15 +674632,20 @@ exports.DefaultFunctionDeployConfig = {
|
|
|
674063
674632
|
ignore: ['node_modules', 'node_modules/**/*', '.git']
|
|
674064
674633
|
};
|
|
674065
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' },
|
|
674066
674637
|
{ name: 'Node.js 20.19', value: 'Nodejs20.19', handler: 'index.main' },
|
|
674067
674638
|
{ name: 'Node.js 18.15', value: 'Nodejs18.15', handler: 'index.main' },
|
|
674068
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' },
|
|
674069
674642
|
{ name: 'Python 3.9', value: 'Python3.9', handler: 'index.main' },
|
|
674070
674643
|
{ name: 'Python 3.7', value: 'Python3.7', handler: 'index.main' },
|
|
674071
674644
|
{ name: 'PHP 8.0', value: 'Php8.0', handler: 'index.main' },
|
|
674072
674645
|
{ name: 'PHP 7.4', value: 'Php7.4', handler: 'index.main' },
|
|
674073
674646
|
{ name: 'Java 11', value: 'Java11', handler: 'example.Hello::mainHandler' },
|
|
674074
|
-
{ 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' }
|
|
674075
674649
|
];
|
|
674076
674650
|
exports.DefaultCloudBaseConfig = {
|
|
674077
674651
|
functionRoot: './functions',
|
|
@@ -731196,6 +731770,7 @@ __exportStar(__webpack_require__(83531), exports);
|
|
|
731196
731770
|
__exportStar(__webpack_require__(12591), exports);
|
|
731197
731771
|
__exportStar(__webpack_require__(78908), exports);
|
|
731198
731772
|
__exportStar(__webpack_require__(5827), exports);
|
|
731773
|
+
__exportStar(__webpack_require__(62600), exports);
|
|
731199
731774
|
__exportStar(__webpack_require__(5892), exports);
|
|
731200
731775
|
|
|
731201
731776
|
|
|
@@ -800745,7 +801320,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
800745
801320
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
800746
801321
|
};
|
|
800747
801322
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
800748
|
-
exports.checkAndCreateBootstrap = exports.generateBootstrapContent = void 0;
|
|
801323
|
+
exports.getConfigSourceDescription = exports.inferFunctionConfig = exports.checkAndCreateBootstrap = exports.generateBootstrapContent = void 0;
|
|
800749
801324
|
const fs_1 = __importDefault(__webpack_require__(79896));
|
|
800750
801325
|
const path_1 = __importDefault(__webpack_require__(16928));
|
|
800751
801326
|
const inquirer_1 = __importDefault(__webpack_require__(6403));
|
|
@@ -800837,6 +801412,206 @@ function checkAndCreateBootstrap(functionPath, func, options = {}) {
|
|
|
800837
801412
|
});
|
|
800838
801413
|
}
|
|
800839
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;
|
|
800840
801615
|
|
|
800841
801616
|
|
|
800842
801617
|
/***/ }),
|
|
@@ -834838,6 +835613,10 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834838
835613
|
{
|
|
834839
835614
|
flags: '--deployMode <deployMode>',
|
|
834840
835615
|
desc: (0, i18n_1.t)('代码上传方式:cos(通过 COS 上传)或 zip(直接 ZIP 上传),默认自动选择')
|
|
835616
|
+
},
|
|
835617
|
+
{
|
|
835618
|
+
flags: '--yes',
|
|
835619
|
+
desc: (0, i18n_1.t)('跳过交互确认,使用推测或默认配置自动部署')
|
|
834841
835620
|
}
|
|
834842
835621
|
],
|
|
834843
835622
|
desc: (0, i18n_1.t)('部署云函数'),
|
|
@@ -834849,7 +835628,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834849
835628
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834850
835629
|
let { envId, config, options } = ctx;
|
|
834851
835630
|
const { functions } = config;
|
|
834852
|
-
const { force, codeSecret, path: access, all, dir, httpFn, ws, deployMode } = options;
|
|
835631
|
+
const { force, codeSecret, path: access, all, dir, httpFn, ws, deployMode, yes } = options;
|
|
834853
835632
|
const name = params === null || params === void 0 ? void 0 : params[0];
|
|
834854
835633
|
this.validateOptions({ deployMode, access }, log);
|
|
834855
835634
|
const isUnresolvedEnvId = !envId || envId.startsWith('{{');
|
|
@@ -834869,12 +835648,12 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834869
835648
|
if (hasConfig) {
|
|
834870
835649
|
return this.deployWithConfig({
|
|
834871
835650
|
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode,
|
|
834872
|
-
all, functions, functionRootPath, log
|
|
835651
|
+
all, functions, functionRootPath, yes, log
|
|
834873
835652
|
});
|
|
834874
835653
|
}
|
|
834875
835654
|
else {
|
|
834876
835655
|
return this.deployWithoutConfig({
|
|
834877
|
-
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, log
|
|
835656
|
+
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, yes, log
|
|
834878
835657
|
});
|
|
834879
835658
|
}
|
|
834880
835659
|
});
|
|
@@ -834893,11 +835672,11 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834893
835672
|
}
|
|
834894
835673
|
deployWithConfig(options) {
|
|
834895
835674
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834896
|
-
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;
|
|
834897
835676
|
if (name) {
|
|
834898
835677
|
return this.deploySingleWithConfig({
|
|
834899
835678
|
name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode,
|
|
834900
|
-
functions, functionRootPath, log
|
|
835679
|
+
functions, functionRootPath, yes, log
|
|
834901
835680
|
});
|
|
834902
835681
|
}
|
|
834903
835682
|
if (dir) {
|
|
@@ -834905,13 +835684,13 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834905
835684
|
}
|
|
834906
835685
|
return this.deployAllFunction({
|
|
834907
835686
|
all, envId, force, access, functions, codeSecret,
|
|
834908
|
-
functionRootPath, httpFn, ws, deployMode, log
|
|
835687
|
+
functionRootPath, httpFn, ws, deployMode, yes, log
|
|
834909
835688
|
});
|
|
834910
835689
|
});
|
|
834911
835690
|
}
|
|
834912
835691
|
deploySingleWithConfig(options) {
|
|
834913
835692
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834914
|
-
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;
|
|
834915
835694
|
let func = functions === null || functions === void 0 ? void 0 : functions.find((item) => item.name === name);
|
|
834916
835695
|
let funcPath;
|
|
834917
835696
|
if (dir) {
|
|
@@ -834934,21 +835713,32 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834934
835713
|
}
|
|
834935
835714
|
if (!func) {
|
|
834936
835715
|
log.warn((0, i18n_1.t)('配置文件中未找到函数 [{{name}}] 的配置', { name }));
|
|
834937
|
-
|
|
834938
|
-
|
|
834939
|
-
|
|
834940
|
-
|
|
834941
|
-
|
|
834942
|
-
|
|
834943
|
-
|
|
834944
|
-
|
|
834945
|
-
|
|
834946
|
-
|
|
834947
|
-
|
|
834948
|
-
|
|
834949
|
-
|
|
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;
|
|
834950
835741
|
}
|
|
834951
|
-
func = defaultFunc;
|
|
834952
835742
|
}
|
|
834953
835743
|
if (httpFn) {
|
|
834954
835744
|
func = Object.assign(Object.assign({}, func), { type: 'HTTP' });
|
|
@@ -834958,95 +835748,177 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
834958
835748
|
}
|
|
834959
835749
|
return this.doDeploySingleFunction({
|
|
834960
835750
|
func, envId, force, codeSecret, access, deployMode,
|
|
834961
|
-
functionRootPath, functionPath: funcPath, log
|
|
835751
|
+
functionRootPath, functionPath: funcPath, yes, log
|
|
834962
835752
|
});
|
|
834963
835753
|
});
|
|
834964
835754
|
}
|
|
834965
835755
|
deployWithoutConfig(options) {
|
|
834966
835756
|
return __awaiter(this, void 0, void 0, function* () {
|
|
834967
|
-
const {
|
|
834968
|
-
|
|
834969
|
-
|
|
834970
|
-
|
|
834971
|
-
|
|
834972
|
-
|
|
834973
|
-
}
|
|
834974
|
-
deployDir = path_1.default.resolve(process.cwd(), dir);
|
|
834975
|
-
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);
|
|
834976
835763
|
}
|
|
834977
|
-
|
|
834978
|
-
|
|
835764
|
+
catch (error) {
|
|
835765
|
+
this.displayFriendlyError(error, {
|
|
835766
|
+
functionName,
|
|
835767
|
+
operation: '前置检测'
|
|
835768
|
+
}, log);
|
|
835769
|
+
checkResult = { uncertain: true, exists: false };
|
|
834979
835770
|
}
|
|
834980
835771
|
let inferredConfig = this.inferFunctionConfig(httpFn, deployDir);
|
|
834981
835772
|
const isInferred = !!inferredConfig;
|
|
834982
835773
|
if (!inferredConfig) {
|
|
834983
|
-
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' } : {}));
|
|
834984
835775
|
}
|
|
834985
|
-
else
|
|
834986
|
-
inferredConfig.name =
|
|
835776
|
+
else {
|
|
835777
|
+
inferredConfig.name = functionName;
|
|
834987
835778
|
}
|
|
834988
835779
|
if (ws && isInferred) {
|
|
834989
835780
|
inferredConfig = Object.assign(Object.assign({}, inferredConfig), { type: 'HTTP', protocolType: 'WS' });
|
|
834990
835781
|
}
|
|
834991
|
-
if (
|
|
834992
|
-
|
|
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);
|
|
834993
835787
|
}
|
|
834994
835788
|
else {
|
|
834995
|
-
|
|
835789
|
+
return yield this.handleNewFunction(inferredConfig, isInferred, options, deployDir);
|
|
834996
835790
|
}
|
|
834997
|
-
|
|
834998
|
-
|
|
834999
|
-
|
|
835000
|
-
|
|
835001
|
-
|
|
835002
|
-
|
|
835003
|
-
|
|
835004
|
-
|
|
835005
|
-
|
|
835006
|
-
|
|
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
|
|
835007
835861
|
});
|
|
835008
|
-
|
|
835009
|
-
|
|
835010
|
-
|
|
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)('⚠ 未推测出配置,将使用默认配置:'));
|
|
835011
835873
|
}
|
|
835012
|
-
|
|
835013
|
-
|
|
835014
|
-
|
|
835874
|
+
this.printFunctionConfig(inferredConfig, log, sourceDesc);
|
|
835875
|
+
let finalConfig = inferredConfig;
|
|
835876
|
+
if (yes) {
|
|
835877
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:跳过交互,自动部署'));
|
|
835015
835878
|
}
|
|
835016
835879
|
else {
|
|
835017
|
-
|
|
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
|
+
}
|
|
835018
835897
|
}
|
|
835019
|
-
return this.doDeploySingleFunction({
|
|
835020
|
-
func
|
|
835021
|
-
|
|
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
|
|
835022
835909
|
});
|
|
835023
835910
|
});
|
|
835024
835911
|
}
|
|
835025
835912
|
inferFunctionConfig(httpFn, deployDir) {
|
|
835026
835913
|
const targetDir = deployDir || process.cwd();
|
|
835027
|
-
const
|
|
835028
|
-
|
|
835029
|
-
return null;
|
|
835030
|
-
}
|
|
835031
|
-
try {
|
|
835032
|
-
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
|
|
835033
|
-
if (!packageJson.name) {
|
|
835034
|
-
return null;
|
|
835035
|
-
}
|
|
835036
|
-
let handler = constant_1.DefaultFunctionDeployConfig.handler;
|
|
835037
|
-
if (packageJson.main) {
|
|
835038
|
-
const mainFile = path_1.default.basename(packageJson.main).replace(/\.[^.]+$/, '');
|
|
835039
|
-
handler = `${mainFile}.main`;
|
|
835040
|
-
}
|
|
835041
|
-
return Object.assign(Object.assign(Object.assign({ name: packageJson.name }, constant_1.DefaultFunctionDeployConfig), { handler }), (httpFn ? { type: 'HTTP' } : {}));
|
|
835042
|
-
}
|
|
835043
|
-
catch (e) {
|
|
835044
|
-
return null;
|
|
835045
|
-
}
|
|
835914
|
+
const result = (0, function_1.inferFunctionConfig)({ targetDir, httpFn });
|
|
835915
|
+
return (result === null || result === void 0 ? void 0 : result.config) || null;
|
|
835046
835916
|
}
|
|
835047
|
-
promptFunctionConfig(defaultConfig, httpFn) {
|
|
835917
|
+
promptFunctionConfig(defaultConfig, httpFn, ws) {
|
|
835048
835918
|
var _a, _b, _c;
|
|
835049
835919
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835920
|
+
const isHttpFnFromCli = httpFn || ws;
|
|
835921
|
+
const isWsFromCli = ws;
|
|
835050
835922
|
const answers = yield inquirer_1.default.prompt([
|
|
835051
835923
|
{
|
|
835052
835924
|
type: 'input',
|
|
@@ -835075,62 +835947,49 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835075
835947
|
name: 'handler',
|
|
835076
835948
|
message: (0, i18n_1.t)('入口函数(格式:文件名.函数名)'),
|
|
835077
835949
|
default: (answers) => {
|
|
835950
|
+
if (defaultConfig.handler) {
|
|
835951
|
+
return defaultConfig.handler;
|
|
835952
|
+
}
|
|
835078
835953
|
const selectedRuntime = constant_1.RuntimeOptions.find(r => r.value === answers.runtime);
|
|
835079
|
-
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;
|
|
835080
835955
|
}
|
|
835081
835956
|
},
|
|
835082
835957
|
{
|
|
835083
835958
|
type: 'confirm',
|
|
835084
835959
|
name: 'isHttpFn',
|
|
835085
835960
|
message: (0, i18n_1.t)('是否为 HTTP 函数'),
|
|
835086
|
-
default:
|
|
835087
|
-
when: !
|
|
835961
|
+
default: isHttpFnFromCli || defaultConfig.type === 'HTTP',
|
|
835962
|
+
when: !isHttpFnFromCli
|
|
835088
835963
|
},
|
|
835089
835964
|
{
|
|
835090
835965
|
type: 'confirm',
|
|
835091
835966
|
name: 'enableWebSocket',
|
|
835092
835967
|
message: (0, i18n_1.t)('是否支持 WebSocket 协议'),
|
|
835093
|
-
default: defaultConfig.protocolType === 'WS',
|
|
835094
|
-
when: (answers) =>
|
|
835968
|
+
default: isWsFromCli || defaultConfig.protocolType === 'WS',
|
|
835969
|
+
when: (answers) => !isWsFromCli && (isHttpFnFromCli || answers.isHttpFn)
|
|
835095
835970
|
},
|
|
835096
835971
|
{
|
|
835097
835972
|
type: 'number',
|
|
835098
835973
|
name: 'timeout',
|
|
835099
835974
|
message: (answers) => {
|
|
835100
|
-
const isWs = answers.enableWebSocket;
|
|
835975
|
+
const isWs = isWsFromCli || answers.enableWebSocket;
|
|
835101
835976
|
return isWs ? (0, i18n_1.t)('超时时间(秒,1-7200)') : (0, i18n_1.t)('超时时间(秒,1-900)');
|
|
835102
835977
|
},
|
|
835103
835978
|
default: defaultConfig.timeout,
|
|
835104
|
-
validate: (input, answers) => {
|
|
835105
|
-
const num = Number(input);
|
|
835106
|
-
const isWs = answers.enableWebSocket;
|
|
835107
|
-
const maxTimeout = isWs ? 7200 : 900;
|
|
835108
|
-
if (isNaN(num) || num < 1 || num > maxTimeout) {
|
|
835109
|
-
return isWs ? (0, i18n_1.t)('超时时间必须在 1-7200 秒之间') : (0, i18n_1.t)('超时时间必须在 1-900 秒之间');
|
|
835110
|
-
}
|
|
835111
|
-
return true;
|
|
835112
|
-
}
|
|
835113
835979
|
},
|
|
835114
835980
|
{
|
|
835115
835981
|
type: 'number',
|
|
835116
835982
|
name: 'idleTimeOut',
|
|
835117
835983
|
message: (0, i18n_1.t)('空闲超时时间(秒,10-7200,默认15)'),
|
|
835118
835984
|
default: ((_b = (_a = defaultConfig.protocolParams) === null || _a === void 0 ? void 0 : _a.wsParams) === null || _b === void 0 ? void 0 : _b.idleTimeOut) || 15,
|
|
835119
|
-
when: (answers) => answers.enableWebSocket,
|
|
835120
|
-
validate: (input) => {
|
|
835121
|
-
const num = Number(input);
|
|
835122
|
-
if (isNaN(num) || num < 10 || num > 7200) {
|
|
835123
|
-
return (0, i18n_1.t)('空闲超时时间必须在 10-7200 秒之间');
|
|
835124
|
-
}
|
|
835125
|
-
return true;
|
|
835126
|
-
}
|
|
835985
|
+
when: (answers) => isWsFromCli || answers.enableWebSocket,
|
|
835127
835986
|
},
|
|
835128
835987
|
{
|
|
835129
835988
|
type: 'confirm',
|
|
835130
835989
|
name: 'enableInstanceConcurrency',
|
|
835131
835990
|
message: (0, i18n_1.t)('是否启用多并发'),
|
|
835132
835991
|
default: !!defaultConfig.instanceConcurrencyConfig,
|
|
835133
|
-
when: (answers) =>
|
|
835992
|
+
when: (answers) => isHttpFnFromCli || answers.isHttpFn
|
|
835134
835993
|
},
|
|
835135
835994
|
{
|
|
835136
835995
|
type: 'number',
|
|
@@ -835166,15 +836025,16 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835166
836025
|
default: defaultConfig.installDependency
|
|
835167
836026
|
}
|
|
835168
836027
|
]);
|
|
835169
|
-
const
|
|
835170
|
-
const
|
|
836028
|
+
const enableWs = isWsFromCli || answers.enableWebSocket;
|
|
836029
|
+
const protocolType = enableWs ? 'WS' : undefined;
|
|
836030
|
+
const protocolParams = (enableWs && answers.idleTimeOut) ? {
|
|
835171
836031
|
wsParams: { idleTimeOut: answers.idleTimeOut }
|
|
835172
836032
|
} : undefined;
|
|
835173
836033
|
const instanceConcurrencyConfig = answers.enableInstanceConcurrency ? {
|
|
835174
836034
|
dynamicEnabled: 'FALSE',
|
|
835175
836035
|
maxConcurrency: answers.maxConcurrency
|
|
835176
836036
|
} : undefined;
|
|
835177
|
-
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 } : {}));
|
|
835178
836038
|
});
|
|
835179
836039
|
}
|
|
835180
836040
|
promptFunctionName() {
|
|
@@ -835193,8 +836053,11 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835193
836053
|
return funcName.trim();
|
|
835194
836054
|
});
|
|
835195
836055
|
}
|
|
835196
|
-
printFunctionConfig(func, log) {
|
|
836056
|
+
printFunctionConfig(func, log, source) {
|
|
835197
836057
|
var _a, _b;
|
|
836058
|
+
if (source) {
|
|
836059
|
+
log.info((0, i18n_1.t)('配置来源:{{source}}', { source }));
|
|
836060
|
+
}
|
|
835198
836061
|
log.info((0, i18n_1.t)(' - 函数名称:{{name}}', { name: func.name }));
|
|
835199
836062
|
log.info((0, i18n_1.t)(' - 运行时:{{runtime}}', { runtime: func.runtime }));
|
|
835200
836063
|
log.info((0, i18n_1.t)(' - 入口函数:{{handler}}', { handler: func.handler }));
|
|
@@ -835217,10 +836080,65 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835217
836080
|
log.info((0, i18n_1.t)(' - 单实例最大并发数:{{num}}', { num: func.instanceConcurrencyConfig.maxConcurrency }));
|
|
835218
836081
|
}
|
|
835219
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)('默认配置');
|
|
835220
836138
|
}
|
|
835221
836139
|
doDeploySingleFunction(options) {
|
|
835222
836140
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835223
|
-
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;
|
|
835224
836142
|
if (func.type === 'HTTP') {
|
|
835225
836143
|
const funcPath = functionPath === '.' ? process.cwd() : (functionPath || path_1.default.join(functionRootPath, func.name));
|
|
835226
836144
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, func);
|
|
@@ -835254,7 +836172,9 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835254
836172
|
func,
|
|
835255
836173
|
accessPath: access,
|
|
835256
836174
|
functionPath,
|
|
835257
|
-
|
|
836175
|
+
yes,
|
|
836176
|
+
logger: log,
|
|
836177
|
+
preCheckResult
|
|
835258
836178
|
});
|
|
835259
836179
|
}
|
|
835260
836180
|
if (access || func.path) {
|
|
@@ -835265,7 +836185,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835265
836185
|
}
|
|
835266
836186
|
deployAllFunction(options) {
|
|
835267
836187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835268
|
-
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;
|
|
835269
836189
|
if (!functions || functions.length === 0) {
|
|
835270
836190
|
functions = this.scanFunctionDirectory(functionRootPath, httpFn);
|
|
835271
836191
|
if (functions.length > 0) {
|
|
@@ -835282,7 +836202,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835282
836202
|
throw new error_1.CloudBaseError((0, i18n_1.t)('未找到云函数配置,请在 cloudbaserc.json 中配置 functions 字段,或使用 tcb fn deploy <函数名> 指定要部署的函数'));
|
|
835283
836203
|
}
|
|
835284
836204
|
let selectedFunctions = functions;
|
|
835285
|
-
if (!all) {
|
|
836205
|
+
if (!all && !yes) {
|
|
835286
836206
|
const choices = functions.map((func) => ({
|
|
835287
836207
|
name: `${func.name}${func.type === 'HTTP' ? ' (HTTP)' : ''}${func.protocolType === 'WS' ? ' (WS)' : ''}`,
|
|
835288
836208
|
value: func.name,
|
|
@@ -835315,7 +836235,60 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835315
836235
|
throw new error_1.CloudBaseError((0, i18n_1.t)('没有选择任何云函数'));
|
|
835316
836236
|
}
|
|
835317
836237
|
}
|
|
836238
|
+
else if (yes) {
|
|
836239
|
+
log.info((0, i18n_1.t)('🚀 --yes 模式:自动部署全部 {{count}} 个函数', { count: functions.length }));
|
|
836240
|
+
}
|
|
835318
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
|
+
}
|
|
835319
836292
|
const tasks = selectedFunctions.map((func) => () => __awaiter(this, void 0, void 0, function* () {
|
|
835320
836293
|
let funcWithType = httpFn ? Object.assign(Object.assign({}, func), { type: 'HTTP' }) : func;
|
|
835321
836294
|
if (ws) {
|
|
@@ -835326,13 +836299,13 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835326
836299
|
: path_1.default.join(functionRootPath, func.name);
|
|
835327
836300
|
if (!fs_1.default.existsSync(funcPath)) {
|
|
835328
836301
|
log.error((0, i18n_1.t)('未找到函数 [{{name}}] 的目录:{{path}},已跳过', { name: func.name, path: funcPath }));
|
|
835329
|
-
return;
|
|
836302
|
+
return { status: 'skipped', name: func.name };
|
|
835330
836303
|
}
|
|
835331
836304
|
if (funcWithType.type === 'HTTP') {
|
|
835332
836305
|
const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, funcWithType);
|
|
835333
836306
|
if (!shouldContinue) {
|
|
835334
836307
|
log.warn((0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }));
|
|
835335
|
-
return;
|
|
836308
|
+
return { status: 'skipped', name: func.name };
|
|
835336
836309
|
}
|
|
835337
836310
|
}
|
|
835338
836311
|
loading.start((0, i18n_1.t)('云函数部署中'));
|
|
@@ -835348,19 +836321,28 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835348
836321
|
deployMode
|
|
835349
836322
|
});
|
|
835350
836323
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数部署成功', { name: func.name }));
|
|
836324
|
+
return { status: 'success', name: func.name };
|
|
835351
836325
|
}
|
|
835352
836326
|
catch (e) {
|
|
835353
836327
|
loading.stop();
|
|
835354
|
-
|
|
835355
|
-
|
|
835356
|
-
|
|
835357
|
-
|
|
835358
|
-
|
|
835359
|
-
|
|
835360
|
-
|
|
835361
|
-
|
|
835362
|
-
|
|
835363
|
-
|
|
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
|
+
}
|
|
835364
836346
|
}
|
|
835365
836347
|
}));
|
|
835366
836348
|
if (tasks.length > 5) {
|
|
@@ -835368,51 +836350,111 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835368
836350
|
}
|
|
835369
836351
|
const asyncTaskController = new utils_1.AsyncTaskParallelController(5, 50);
|
|
835370
836352
|
asyncTaskController.loadTasks(tasks);
|
|
835371
|
-
const
|
|
835372
|
-
const
|
|
835373
|
-
|
|
835374
|
-
|
|
835375
|
-
|
|
835376
|
-
|
|
835377
|
-
|
|
835378
|
-
|
|
835379
|
-
|
|
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
|
+
}
|
|
835380
836393
|
}
|
|
835381
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)('没有函数被部署'));
|
|
835382
836401
|
}
|
|
835383
836402
|
});
|
|
835384
836403
|
}
|
|
835385
836404
|
handleDeployFail(e, options) {
|
|
836405
|
+
var _a;
|
|
835386
836406
|
return __awaiter(this, void 0, void 0, function* () {
|
|
835387
|
-
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;
|
|
835388
836408
|
let func = originalFunc;
|
|
835389
836409
|
const loading = (0, utils_1.loadingFactory)();
|
|
835390
|
-
|
|
835391
|
-
|
|
835392
|
-
|
|
835393
|
-
|
|
835394
|
-
|
|
835395
|
-
|
|
835396
|
-
|
|
835397
|
-
|
|
835398
|
-
|
|
835399
|
-
|
|
835400
|
-
|
|
835401
|
-
|
|
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 调用'));
|
|
835402
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';
|
|
835403
836447
|
const existingProtocolType = (existingFunction === null || existingFunction === void 0 ? void 0 : existingFunction.ProtocolType) || '';
|
|
835404
|
-
const
|
|
835405
|
-
|
|
835406
|
-
|
|
835407
|
-
|
|
835408
|
-
|
|
835409
|
-
|
|
835410
|
-
}));
|
|
835411
|
-
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 }));
|
|
835412
836455
|
}
|
|
835413
|
-
|
|
835414
|
-
|
|
835415
|
-
if (!shouldForce) {
|
|
836456
|
+
let shouldForce = forceOverwrite || yes;
|
|
836457
|
+
if (!shouldForce && !batchMode) {
|
|
835416
836458
|
const answer = yield inquirer_1.default.prompt({
|
|
835417
836459
|
type: 'confirm',
|
|
835418
836460
|
name: 'force',
|
|
@@ -835421,9 +836463,12 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835421
836463
|
});
|
|
835422
836464
|
shouldForce = answer.force;
|
|
835423
836465
|
}
|
|
835424
|
-
|
|
836466
|
+
else if (!shouldForce && batchMode) {
|
|
836467
|
+
(log || utils_1.logger).info((0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }));
|
|
836468
|
+
return 'cancelled';
|
|
836469
|
+
}
|
|
835425
836470
|
if (shouldForce) {
|
|
835426
|
-
loading.start((0, i18n_1.t)('云函数更新部署中...'));
|
|
836471
|
+
loading.start(batchMode ? (0, i18n_1.t)('云函数 [{{name}}] 更新部署中...', { name: func.name }) : (0, i18n_1.t)('云函数更新部署中...'));
|
|
835427
836472
|
try {
|
|
835428
836473
|
yield (0, function_2.updateFunctionCode)({
|
|
835429
836474
|
func,
|
|
@@ -835434,7 +836479,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835434
836479
|
});
|
|
835435
836480
|
const success = yield this.waitForFunctionReady(envId, func.name, loading);
|
|
835436
836481
|
if (!success) {
|
|
835437
|
-
return;
|
|
836482
|
+
return 'error';
|
|
835438
836483
|
}
|
|
835439
836484
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数配置更新中...', { name: func.name }));
|
|
835440
836485
|
yield (0, function_2.updateFunctionConfig)({
|
|
@@ -835443,7 +836488,10 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835443
836488
|
config: func
|
|
835444
836489
|
});
|
|
835445
836490
|
loading.succeed((0, i18n_1.t)('[{{name}}] 云函数更新成功!', { name: func.name }));
|
|
835446
|
-
|
|
836491
|
+
if (!batchMode) {
|
|
836492
|
+
yield this.printSuccessTips(envId);
|
|
836493
|
+
}
|
|
836494
|
+
return 'success';
|
|
835447
836495
|
}
|
|
835448
836496
|
catch (e) {
|
|
835449
836497
|
loading.stop();
|
|
@@ -835451,9 +836499,9 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835451
836499
|
}
|
|
835452
836500
|
}
|
|
835453
836501
|
else {
|
|
835454
|
-
(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';
|
|
835455
836504
|
}
|
|
835456
|
-
return;
|
|
835457
836505
|
}
|
|
835458
836506
|
throw e;
|
|
835459
836507
|
});
|
|
@@ -835571,6 +836619,284 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
|
|
|
835571
836619
|
return runtime;
|
|
835572
836620
|
});
|
|
835573
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
|
+
}
|
|
835574
836900
|
};
|
|
835575
836901
|
__decorate([
|
|
835576
836902
|
(0, decorators_1.InjectParams)(),
|