@cloudbase/cli 2.12.6 → 2.12.8

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.
Files changed (2) hide show
  1. package/dist/standalone/cli.js +622 -329
  2. package/package.json +1 -1
@@ -2447,6 +2447,80 @@ function* pattern(...rest) {
2447
2447
  }
2448
2448
  //# sourceMappingURL=exec.js.map
2449
2449
 
2450
+ /***/ }),
2451
+
2452
+ /***/ 325:
2453
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
2454
+
2455
+ "use strict";
2456
+
2457
+ var __importDefault = (this && this.__importDefault) || function (mod) {
2458
+ return (mod && mod.__esModule) ? mod : { "default": mod };
2459
+ };
2460
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2461
+ exports.validateImageDeploy = exports.resolveFuncPathWithConfig = exports.resolveFunctionName = exports.resolveAndValidateFunctionDir = void 0;
2462
+ const path_1 = __importDefault(__webpack_require__(16928));
2463
+ const error_1 = __webpack_require__(66759);
2464
+ const i18n_1 = __webpack_require__(69258);
2465
+ const utils_1 = __webpack_require__(82079);
2466
+ function resolveAndValidateFunctionDir(options) {
2467
+ const { dir, defaultDir, action, log } = options;
2468
+ let targetDir = defaultDir;
2469
+ if (dir) {
2470
+ (0, utils_1.checkFullAccess)(dir, true);
2471
+ if (!(0, utils_1.isDirectory)(dir)) {
2472
+ throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
2473
+ }
2474
+ targetDir = path_1.default.resolve(defaultDir, dir);
2475
+ log === null || log === void 0 ? void 0 : log.info((0, i18n_1.t)(`将从目录 {{dir}} ${action}云函数`, { dir: targetDir }));
2476
+ }
2477
+ else {
2478
+ log === null || log === void 0 ? void 0 : log.info((0, i18n_1.t)(`未找到配置文件,将从当前目录${action}云函数`));
2479
+ }
2480
+ return targetDir;
2481
+ }
2482
+ exports.resolveAndValidateFunctionDir = resolveAndValidateFunctionDir;
2483
+ function resolveFunctionName(name, deployDir) {
2484
+ return name || path_1.default.basename(deployDir);
2485
+ }
2486
+ exports.resolveFunctionName = resolveFunctionName;
2487
+ function resolveFuncPathWithConfig(options) {
2488
+ const { dir, funcDir, functionRootPath, name, deployMode, log } = options;
2489
+ if (deployMode === 'image') {
2490
+ return '';
2491
+ }
2492
+ let funcPath = '';
2493
+ if (dir) {
2494
+ (0, utils_1.checkFullAccess)(dir, true);
2495
+ if (!(0, utils_1.isDirectory)(dir)) {
2496
+ throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
2497
+ }
2498
+ funcPath = path_1.default.resolve(process.cwd(), dir);
2499
+ log.info((0, i18n_1.t)('使用命令行指定的目录:{{path}}', { path: funcPath }));
2500
+ }
2501
+ else if (funcDir) {
2502
+ funcPath = path_1.default.resolve(process.cwd(), funcDir);
2503
+ log.info((0, i18n_1.t)('使用配置文件中的目录:{{path}}', { path: funcPath }));
2504
+ }
2505
+ else {
2506
+ funcPath = path_1.default.join(functionRootPath, name);
2507
+ }
2508
+ return funcPath;
2509
+ }
2510
+ exports.resolveFuncPathWithConfig = resolveFuncPathWithConfig;
2511
+ function validateImageDeploy(deployMode, hasConfig) {
2512
+ if (deployMode === 'image') {
2513
+ if (hasConfig === false) {
2514
+ throw new error_1.CloudBaseError((0, i18n_1.t)('镜像部署时需要在配置文件中指定 imageConfig'));
2515
+ }
2516
+ if (hasConfig === undefined) {
2517
+ throw new error_1.CloudBaseError((0, i18n_1.t)('镜像部署时需要在配置文件中指定函数配置和 imageConfig'));
2518
+ }
2519
+ }
2520
+ }
2521
+ exports.validateImageDeploy = validateImageDeploy;
2522
+
2523
+
2450
2524
  /***/ }),
2451
2525
 
2452
2526
  /***/ 340:
@@ -326254,7 +326328,7 @@ module.exports = function generate_pattern(it, $keyword, $ruleType) {
326254
326328
  /***/ ((module) => {
326255
326329
 
326256
326330
  "use strict";
326257
- module.exports = /*#__PURE__*/JSON.parse('{"name":"@cloudbase/cli","version":"2.12.6","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.10.2","@cloudbase/toolbox":"0.7.17","@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 - 腾讯云云开发命令行工具,支持云函数、云数据库、静态托管等全栈云开发能力"}}');
326331
+ module.exports = /*#__PURE__*/JSON.parse('{"name":"@cloudbase/cli","version":"2.12.8","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.10.6","@cloudbase/toolbox":"0.7.17","@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 - 腾讯云云开发命令行工具,支持云函数、云数据库、静态托管等全栈云开发能力"}}');
326258
326332
 
326259
326333
  /***/ }),
326260
326334
 
@@ -467668,6 +467742,7 @@ const decorators_1 = __webpack_require__(93480);
467668
467742
  const i18n_1 = __webpack_require__(69258);
467669
467743
  const utils_2 = __webpack_require__(75213);
467670
467744
  const constant_1 = __webpack_require__(62977);
467745
+ const common_utils_1 = __webpack_require__(325);
467671
467746
  let CodeUpdate = class CodeUpdate extends common_1.Command {
467672
467747
  get options() {
467673
467748
  return {
@@ -467723,9 +467798,7 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
467723
467798
  }
467724
467799
  const configFiles = ['cloudbaserc.json', 'cloudbaserc.js', 'cloudbaserc.yaml', 'cloudbaserc.yml', 'cloudbaserc', 'cloudbase.config.js'];
467725
467800
  const hasConfigFile = configFiles.some(file => fs_1.default.existsSync(path_1.default.join(process.cwd(), file)));
467726
- if (deployMode === 'image' && !hasConfigFile) {
467727
- throw new error_1.CloudBaseError((0, i18n_1.t)('镜像部署时需要在配置文件中指定 imageConfig,请创建 cloudbaserc.json 并配置镜像参数'));
467728
- }
467801
+ (0, common_utils_1.validateImageDeploy)(deployMode, hasConfigFile ? undefined : false);
467729
467802
  const hasConfig = hasConfigFile || functions.length > 0;
467730
467803
  if (hasConfig) {
467731
467804
  return this.updateWithConfig({ name, dir, envId, codeSecret, deployMode, config, functions, log });
@@ -467743,26 +467816,19 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
467743
467816
  log.info((0, i18n_1.t)('从配置文件读取函数 [{{name}}] 的配置', { name }));
467744
467817
  }
467745
467818
  else {
467819
+ (0, common_utils_1.validateImageDeploy)(deployMode, undefined);
467746
467820
  func = Object.assign({ name }, constant_1.DefaultFunctionDeployConfig);
467747
467821
  log.info((0, i18n_1.t)('未找到函数 [{{name}}] 的配置,使用默认配置', { name }));
467748
467822
  }
467749
467823
  const functionRootPath = path_1.default.join(process.cwd(), config.functionRoot || 'functions');
467750
- let funcPath;
467751
- if (dir) {
467752
- (0, utils_1.checkFullAccess)(dir, true);
467753
- if (!(0, utils_1.isDirectory)(dir)) {
467754
- throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
467755
- }
467756
- funcPath = path_1.default.resolve(process.cwd(), dir);
467757
- log.info((0, i18n_1.t)('使用命令行指定的目录:{{path}}', { path: funcPath }));
467758
- }
467759
- else if (func === null || func === void 0 ? void 0 : func.dir) {
467760
- funcPath = path_1.default.resolve(process.cwd(), func.dir);
467761
- log.info((0, i18n_1.t)('使用配置文件中的目录:{{path}}', { path: funcPath }));
467762
- }
467763
- else {
467764
- funcPath = path_1.default.join(functionRootPath, name);
467765
- }
467824
+ const funcPath = (0, common_utils_1.resolveFuncPathWithConfig)({
467825
+ dir,
467826
+ funcDir: func === null || func === void 0 ? void 0 : func.dir,
467827
+ functionRootPath,
467828
+ name,
467829
+ deployMode,
467830
+ log
467831
+ });
467766
467832
  return this.doUpdateCode({
467767
467833
  func, funcPath, functionRootPath, envId, codeSecret, deployMode,
467768
467834
  functionPath: dir ? funcPath : undefined, log
@@ -467772,18 +467838,13 @@ let CodeUpdate = class CodeUpdate extends common_1.Command {
467772
467838
  updateWithoutConfig(options) {
467773
467839
  return __awaiter(this, void 0, void 0, function* () {
467774
467840
  const { name, dir, envId, codeSecret, deployMode, log } = options;
467775
- let updateDir = process.cwd();
467776
- if (dir) {
467777
- (0, utils_1.checkFullAccess)(dir, true);
467778
- if (!(0, utils_1.isDirectory)(dir)) {
467779
- throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
467780
- }
467781
- updateDir = path_1.default.resolve(process.cwd(), dir);
467782
- log.info((0, i18n_1.t)('将从目录 {{dir}} 更新云函数代码', { dir: updateDir }));
467783
- }
467784
- else {
467785
- log.info((0, i18n_1.t)('未找到配置文件,将从当前目录更新云函数代码'));
467786
- }
467841
+ (0, common_utils_1.validateImageDeploy)(deployMode, false);
467842
+ const updateDir = (0, common_utils_1.resolveAndValidateFunctionDir)({
467843
+ dir,
467844
+ defaultDir: process.cwd(),
467845
+ action: '更新',
467846
+ log
467847
+ });
467787
467848
  let inferredConfig = this.inferFunctionConfig(name, updateDir);
467788
467849
  const isInferred = !!inferredConfig;
467789
467850
  if (!inferredConfig) {
@@ -694008,9 +694069,10 @@ function updateFunctionCode(options) {
694008
694069
  });
694009
694070
  }
694010
694071
  catch (e) {
694011
- throw new error_1.CloudBaseError((0, i18n_1.t)('[{{name}}] 函数代码更新失败: {{error}}', { name: funcName, error: e.message }), {
694072
+ throw new error_1.CloudBaseError((0, i18n_1.t)('[{{name}}] 函数代码更新失败: {{error}}', { name: funcName, error: e.message || String(e) }), {
694012
694073
  code: e.code,
694013
- requestId: e.requestId
694074
+ requestId: e.requestId,
694075
+ original: e
694014
694076
  });
694015
694077
  }
694016
694078
  });
@@ -724302,21 +724364,27 @@ class StorageService {
724302
724364
  Error
724303
724365
  };
724304
724366
  }
724305
- /**
724306
- * 获取文件存储权限
724307
- * READONLY:所有用户可读,仅创建者和管理员可写
724308
- * PRIVATE:仅创建者及管理员可读写
724309
- * ADMINWRITE:所有用户可读,仅管理员可写
724310
- * ADMINONLY:仅管理员可读写
724311
- * @returns
724312
- */
724313
- async getStorageAcl() {
724367
+ async getStorageAcl(options) {
724314
724368
  const { bucket, env } = this.getStorageConfig();
724315
- const res = await this.tcbService.request('DescribeStorageACL', {
724369
+ const res = await this.tcbService.request('DescribeStorageSafeRule', {
724316
724370
  EnvId: env,
724317
724371
  Bucket: bucket
724318
724372
  });
724319
- return res.AclTag;
724373
+ // 默认行为:返回简单的 AclType(向后兼容)
724374
+ if (!(options === null || options === void 0 ? void 0 : options.withRule)) {
724375
+ return res.AclTag;
724376
+ }
724377
+ // 带规则模式:返回对象
724378
+ const result = { acl: res.AclTag };
724379
+ if (res.AclTag === 'CUSTOM' && res.Rule) {
724380
+ try {
724381
+ result.rule = JSON.parse(res.Rule);
724382
+ }
724383
+ catch (_a) {
724384
+ // Rule 可能不是 JSON 格式,忽略解析错误
724385
+ }
724386
+ }
724387
+ return result;
724320
724388
  }
724321
724389
  /**
724322
724390
  * 设置文件存储权限
@@ -724324,20 +724392,38 @@ class StorageService {
724324
724392
  * PRIVATE:仅创建者及管理员可读写
724325
724393
  * ADMINWRITE:所有用户可读,仅管理员可写
724326
724394
  * ADMINONLY:仅管理员可读写
724327
- * @param {string} acl
724395
+ * CUSTOM:自定义安全规则(需要传入 rule 参数)
724396
+ * @param {AclType} acl 权限类型
724397
+ * @param {IStorageAclRule} [rule] 自定义安全规则,当 acl 为 CUSTOM 时必填
724328
724398
  * @returns
724399
+ * @example
724400
+ * // 设置简易权限
724401
+ * await storage.setStorageAcl('READONLY')
724402
+ *
724403
+ * // 设置自定义安全规则
724404
+ * await storage.setStorageAcl('CUSTOM', {
724405
+ * read: true,
724406
+ * write: 'resource.openid == auth.uid'
724407
+ * })
724329
724408
  */
724330
- async setStorageAcl(acl) {
724331
- const validAcl = ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY'];
724409
+ async setStorageAcl(acl, rule) {
724410
+ const validAcl = ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY', 'CUSTOM'];
724332
724411
  if (!validAcl.includes(acl)) {
724333
- throw new error_1.CloudBaseError('非法的权限类型');
724412
+ throw new error_1.CloudBaseError(`非法的权限类型: "${acl}", 有效值: ${validAcl.join(', ')}`);
724413
+ }
724414
+ if (acl === 'CUSTOM' && !rule) {
724415
+ throw new error_1.CloudBaseError('使用 CUSTOM 权限类型时,必须提供 rule 参数');
724334
724416
  }
724335
724417
  const { bucket, env } = this.getStorageConfig();
724336
- return this.tcbService.request('ModifyStorageACL', {
724418
+ const params = {
724337
724419
  EnvId: env,
724338
724420
  Bucket: bucket,
724339
724421
  AclTag: acl
724340
- });
724422
+ };
724423
+ if (acl === 'CUSTOM' && rule) {
724424
+ params.Rule = JSON.stringify(rule);
724425
+ }
724426
+ return this.tcbService.request('ModifyStorageSafeRule', params);
724341
724427
  }
724342
724428
  /**
724343
724429
  * 遍历云端文件夹
@@ -726148,7 +726234,9 @@ const outputHelpInfo = () => {
726148
726234
  hosting [cmd] ${(0, i18n_1.t)('静态托管资源管理操作')}
726149
726235
  storage [cmd] ${(0, i18n_1.t)('云存储资源管理操作')}
726150
726236
  service [cmd] ${(0, i18n_1.t)('HTTP 访问服务管理操作')}
726151
- cloudrun [cmd] ${(0, i18n_1.t)('云托管服务管理操作`')}
726237
+ cloudrun [cmd] ${(0, i18n_1.t)('云托管服务管理操作')}
726238
+ config [cmd] ${(0, i18n_1.t)('配置文件管理操作')}
726239
+ gateway [cmd] ${(0, i18n_1.t)('网关管理操作')}
726152
726240
  `;
726153
726241
  const options = `
726154
726242
  ${(0, i18n_1.t)('选项')}
@@ -730339,8 +730427,8 @@ let GetAclCommand = class GetAclCommand extends common_1.Command {
730339
730427
  execute(envId) {
730340
730428
  return __awaiter(this, void 0, void 0, function* () {
730341
730429
  const storageService = yield getStorageService(envId);
730342
- const acl = yield storageService.getStorageAcl();
730343
- console.log((0, i18n_1.t)('当前权限【{{acl}}】', { acl: AclMap[acl] }));
730430
+ const acl = yield storageService.getStorageAcl({ withRule: true });
730431
+ console.log((0, i18n_1.t)('当前权限【{{acl}}】', { acl: AclMap[acl.acl] }));
730344
730432
  });
730345
730433
  }
730346
730434
  };
@@ -801619,9 +801707,12 @@ function inferNodejsConfig(targetDir, name, httpFn) {
801619
801707
  runtime = 'Nodejs16.13';
801620
801708
  }
801621
801709
  }
801710
+ const hasDependencies = Boolean(packageJson.dependencies && Object.keys(packageJson.dependencies).length > 0);
801711
+ const hasDevDependencies = Boolean(packageJson.devDependencies && Object.keys(packageJson.devDependencies).length > 0);
801712
+ const shouldInstallDeps = hasDependencies || hasDevDependencies;
801622
801713
  return {
801623
- config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime,
801624
- handler, installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
801714
+ config: Object.assign(Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime,
801715
+ handler }), (shouldInstallDeps ? { installDependency: true } : {})), (httpFn ? { type: 'HTTP' } : {})),
801625
801716
  source: (0, i18n_1.t)('Node.js 项目(package.json)')
801626
801717
  };
801627
801718
  }
@@ -801646,7 +801737,7 @@ function inferPythonConfig(targetDir, name, httpFn) {
801646
801737
  }
801647
801738
  }
801648
801739
  return {
801649
- config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Python3.9', handler, installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
801740
+ config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Python3.9', handler }), (httpFn ? { type: 'HTTP' } : {})),
801650
801741
  source: (0, i18n_1.t)('Python 项目({{file}})', { file: foundFile })
801651
801742
  };
801652
801743
  }
@@ -801679,7 +801770,7 @@ function inferPhpConfig(targetDir, name, httpFn) {
801679
801770
  handler = 'index.main';
801680
801771
  }
801681
801772
  return {
801682
- 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' } : {})),
801773
+ config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Php8.0', handler }), (httpFn ? { type: 'HTTP' } : {})),
801683
801774
  source
801684
801775
  };
801685
801776
  }
@@ -801703,7 +801794,7 @@ function inferJavaConfig(targetDir, name, httpFn) {
801703
801794
  }
801704
801795
  }
801705
801796
  return {
801706
- config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Java11', handler: 'example.Hello::mainHandler', installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
801797
+ config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Java11', handler: 'example.Hello::mainHandler' }), (httpFn ? { type: 'HTTP' } : {})),
801707
801798
  source: (0, i18n_1.t)('Java 项目({{file}})', { file: foundFile })
801708
801799
  };
801709
801800
  }
@@ -801726,7 +801817,7 @@ function inferGoConfig(targetDir, name, httpFn) {
801726
801817
  }
801727
801818
  }
801728
801819
  return {
801729
- config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Go1', handler: 'main', installDependency: true }), (httpFn ? { type: 'HTTP' } : {})),
801820
+ config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: 'Go1', handler: 'main' }), (httpFn ? { type: 'HTTP' } : {})),
801730
801821
  source: (0, i18n_1.t)('Go 项目({{file}})', { file: foundFile })
801731
801822
  };
801732
801823
  }
@@ -801759,7 +801850,7 @@ function inferByFileExtension(targetDir, name, httpFn) {
801759
801850
  return null;
801760
801851
  }
801761
801852
  return {
801762
- config: Object.assign(Object.assign(Object.assign({ name: funcName }, constant_1.DefaultFunctionDeployConfig), { runtime: typeConfig.runtime, handler: typeConfig.handler }), (httpFn ? { type: 'HTTP' } : {})),
801853
+ config: Object.assign({ name: funcName, timeout: constant_1.DefaultFunctionDeployConfig.timeout, runtime: typeConfig.runtime, handler: typeConfig.handler, ignore: constant_1.DefaultFunctionDeployConfig.ignore }, (httpFn ? { type: 'HTTP' } : {})),
801763
801854
  source: typeConfig.source
801764
801855
  };
801765
801856
  }
@@ -835731,6 +835822,27 @@ const decorators_1 = __webpack_require__(93480);
835731
835822
  const function_2 = __webpack_require__(11686);
835732
835823
  const i18n_1 = __webpack_require__(69258);
835733
835824
  const utils_2 = __webpack_require__(75213);
835825
+ const common_utils_1 = __webpack_require__(325);
835826
+ const MAX_PARALLEL_DEPLOY = 5;
835827
+ function buildImageConfig(functionConf) {
835828
+ const fileImageConfig = (0, function_2.buildImageConfigFromConfig)(functionConf);
835829
+ if (!fileImageConfig) {
835830
+ return null;
835831
+ }
835832
+ return fileImageConfig;
835833
+ }
835834
+ function checkWebFunctionBootstrap(functionPath, functionConf) {
835835
+ return __awaiter(this, void 0, void 0, function* () {
835836
+ return yield (0, function_1.checkAndCreateBootstrap)(functionPath, functionConf);
835837
+ });
835838
+ }
835839
+ function resolveFunctionPath(options) {
835840
+ const { functionRootPath, functionName, functionDirFromConfig } = options;
835841
+ if (functionDirFromConfig) {
835842
+ return path_1.default.resolve(process.cwd(), functionDirFromConfig);
835843
+ }
835844
+ return path_1.default.join(functionRootPath, functionName);
835845
+ }
835734
835846
  let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835735
835847
  get options() {
835736
835848
  return {
@@ -835852,26 +835964,29 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835852
835964
  return __awaiter(this, void 0, void 0, function* () {
835853
835965
  const { name, dir, envId, force, codeSecret, access, httpFn, ws, deployMode, functions, functionRootPath, yes, log } = options;
835854
835966
  let func = functions === null || functions === void 0 ? void 0 : functions.find((item) => item.name === name);
835855
- let funcPath;
835856
- if (dir) {
835857
- (0, utils_1.checkFullAccess)(dir, true);
835858
- if (!(0, utils_1.isDirectory)(dir)) {
835859
- throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
835967
+ let funcPath = '';
835968
+ if (deployMode !== 'image') {
835969
+ if (dir) {
835970
+ (0, utils_1.checkFullAccess)(dir, true);
835971
+ if (!(0, utils_1.isDirectory)(dir)) {
835972
+ throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
835973
+ }
835974
+ funcPath = path_1.default.resolve(process.cwd(), dir);
835975
+ log.info((0, i18n_1.t)('使用命令行指定的目录:{{path}}', { path: funcPath }));
835976
+ }
835977
+ else if (func === null || func === void 0 ? void 0 : func.dir) {
835978
+ funcPath = path_1.default.resolve(process.cwd(), func.dir);
835979
+ log.info((0, i18n_1.t)('使用配置文件中的目录:{{path}}', { path: funcPath }));
835980
+ }
835981
+ else {
835982
+ funcPath = path_1.default.join(functionRootPath, name);
835983
+ }
835984
+ if (!fs_1.default.existsSync(funcPath)) {
835985
+ throw new error_1.CloudBaseError((0, i18n_1.t)('未找到函数 [{{name}}] 的目录:{{path}},请检查函数名称或使用 --dir 指定函数目录', { name, path: funcPath }));
835860
835986
  }
835861
- funcPath = path_1.default.resolve(process.cwd(), dir);
835862
- log.info((0, i18n_1.t)('使用命令行指定的目录:{{path}}', { path: funcPath }));
835863
- }
835864
- else if (func === null || func === void 0 ? void 0 : func.dir) {
835865
- funcPath = path_1.default.resolve(process.cwd(), func.dir);
835866
- log.info((0, i18n_1.t)('使用配置文件中的目录:{{path}}', { path: funcPath }));
835867
- }
835868
- else {
835869
- funcPath = path_1.default.join(functionRootPath, name);
835870
- }
835871
- if (!fs_1.default.existsSync(funcPath)) {
835872
- throw new error_1.CloudBaseError((0, i18n_1.t)('未找到函数 [{{name}}] 的目录:{{path}},请检查函数名称或使用 --dir 指定函数目录', { name, path: funcPath }));
835873
835987
  }
835874
835988
  if (!func) {
835989
+ (0, common_utils_1.validateImageDeploy)(deployMode, undefined);
835875
835990
  log.warn((0, i18n_1.t)('配置文件中未找到函数 [{{name}}] 的配置', { name }));
835876
835991
  if (yes) {
835877
835992
  const inferredConfig = this.inferFunctionConfig(httpFn, funcPath);
@@ -835914,7 +836029,8 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835914
836029
  }
835915
836030
  deployWithoutConfig(options) {
835916
836031
  return __awaiter(this, void 0, void 0, function* () {
835917
- const { envId, codeSecret, httpFn, ws, log } = options;
836032
+ const { envId, codeSecret, httpFn, ws, deployMode, log } = options;
836033
+ (0, common_utils_1.validateImageDeploy)(deployMode, false);
835918
836034
  const { deployDir, functionName } = this.resolveFunctionInfo(options);
835919
836035
  log.verbose((0, i18n_1.t)('正在检测云端函数状态...'));
835920
836036
  let checkResult;
@@ -835952,19 +836068,13 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835952
836068
  }
835953
836069
  resolveFunctionInfo(options) {
835954
836070
  const { name, dir, log } = options;
835955
- let deployDir = process.cwd();
835956
- if (dir) {
835957
- (0, utils_1.checkFullAccess)(dir, true);
835958
- if (!(0, utils_1.isDirectory)(dir)) {
835959
- throw new error_1.CloudBaseError((0, i18n_1.t)('--dir 参数必须指定为云函数的文件夹路径'));
835960
- }
835961
- deployDir = path_1.default.resolve(process.cwd(), dir);
835962
- log.info((0, i18n_1.t)('将从目录 {{dir}} 部署云函数', { dir: deployDir }));
835963
- }
835964
- else {
835965
- log.info((0, i18n_1.t)('未找到配置文件,将从当前目录部署云函数'));
835966
- }
835967
- const functionName = name || path_1.default.basename(deployDir);
836071
+ const deployDir = (0, common_utils_1.resolveAndValidateFunctionDir)({
836072
+ dir,
836073
+ defaultDir: process.cwd(),
836074
+ action: '部署',
836075
+ log
836076
+ });
836077
+ const functionName = (0, common_utils_1.resolveFunctionName)(name, deployDir);
835968
836078
  return { deployDir, functionName };
835969
836079
  }
835970
836080
  handleExistingFunction(checkResult, inferredConfig, isInferred, options, deployDir) {
@@ -835972,7 +836082,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835972
836082
  const { envId, force, codeSecret, access, deployMode, yes, log } = options;
835973
836083
  const conflicts = this.detectConfigConflicts(inferredConfig, checkResult.functionDetail);
835974
836084
  if (conflicts.length > 0) {
835975
- this.displayConfigConflicts(inferredConfig.name, conflicts);
836085
+ this.displayConfigConflicts(inferredConfig.name, conflicts, log);
835976
836086
  throw new error_1.CloudBaseError((0, i18n_1.t)('配置冲突,无法部署'));
835977
836087
  }
835978
836088
  let shouldUpdate = force || yes;
@@ -835985,7 +836095,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
835985
836095
  }
835986
836096
  const mergedConfig = this.mergeCloudAndLocalConfig(checkResult.functionDetail, inferredConfig);
835987
836097
  log.info((0, i18n_1.t)('✓ 函数已存在,将使用以下合并配置更新:'));
835988
- this.displayMergedConfig(inferredConfig.name, mergedConfig, isInferred ? 'inferred' : 'default');
836098
+ this.displayMergedConfig(inferredConfig.name, mergedConfig, isInferred ? 'inferred' : 'default', log);
835989
836099
  let finalConfig = mergedConfig;
835990
836100
  if (!yes) {
835991
836101
  const { action } = yield inquirer_1.default.prompt({
@@ -836182,7 +836292,11 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836182
836292
  type: 'confirm',
836183
836293
  name: 'installDependency',
836184
836294
  message: (0, i18n_1.t)('是否在线安装依赖'),
836185
- default: defaultConfig.installDependency
836295
+ default: defaultConfig.installDependency,
836296
+ when: (answers) => {
836297
+ const runtime = answers.runtime || defaultConfig.runtime;
836298
+ return runtime === null || runtime === void 0 ? void 0 : runtime.startsWith('Nodejs');
836299
+ }
836186
836300
  }
836187
836301
  ]);
836188
836302
  const enableWs = isWsFromCli || answers.enableWebSocket;
@@ -836194,7 +836308,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836194
836308
  dynamicEnabled: 'FALSE',
836195
836309
  maxConcurrency: answers.maxConcurrency
836196
836310
  } : undefined;
836197
- 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 } : {}));
836311
+ return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ name: answers.name.trim(), runtime: answers.runtime, handler: answers.handler, timeout: answers.timeout, memorySize: answers.memorySize }, (answers.installDependency !== undefined ? { installDependency: answers.installDependency } : {})), { ignore: defaultConfig.ignore || constant_1.DefaultFunctionDeployConfig.ignore }), (isHttpFnFromCli || answers.isHttpFn ? { type: 'HTTP' } : {})), (protocolType ? { protocolType } : {})), (protocolParams ? { protocolParams } : {})), (instanceConcurrencyConfig ? { instanceConcurrencyConfig } : {}));
836198
836312
  });
836199
836313
  }
836200
836314
  promptFunctionName() {
@@ -836214,7 +836328,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836214
836328
  });
836215
836329
  }
836216
836330
  printFunctionConfig(func, log, source) {
836217
- var _a, _b;
836331
+ var _a, _b, _c;
836218
836332
  if (source) {
836219
836333
  log.info((0, i18n_1.t)('配置来源:{{source}}', { source }));
836220
836334
  }
@@ -836225,12 +836339,14 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836225
836339
  if (func.memorySize) {
836226
836340
  log.info((0, i18n_1.t)(' - 内存大小:{{memorySize}} MB', { memorySize: func.memorySize }));
836227
836341
  }
836228
- log.info((0, i18n_1.t)(' - 在线安装依赖:{{installDependency}}', { installDependency: func.installDependency ? (0, i18n_1.t)('') : (0, i18n_1.t)('否') }));
836342
+ if (((_a = func.runtime) === null || _a === void 0 ? void 0 : _a.startsWith('Nodejs')) && func.installDependency !== undefined) {
836343
+ log.info((0, i18n_1.t)(' - 在线安装依赖:{{installDependency}}', { installDependency: func.installDependency ? (0, i18n_1.t)('是') : (0, i18n_1.t)('否') }));
836344
+ }
836229
836345
  if (func.type === 'HTTP') {
836230
836346
  log.info((0, i18n_1.t)(' - 函数类型:HTTP'));
836231
836347
  if (func.protocolType === 'WS') {
836232
836348
  log.info((0, i18n_1.t)(' - WebSocket 协议:已启用'));
836233
- const idleTimeOut = (_b = (_a = func.protocolParams) === null || _a === void 0 ? void 0 : _a.wsParams) === null || _b === void 0 ? void 0 : _b.idleTimeOut;
836349
+ const idleTimeOut = (_c = (_b = func.protocolParams) === null || _b === void 0 ? void 0 : _b.wsParams) === null || _c === void 0 ? void 0 : _c.idleTimeOut;
836234
836350
  if (idleTimeOut) {
836235
836351
  log.info((0, i18n_1.t)(' - 空闲超时时间:{{seconds}} 秒', { seconds: idleTimeOut }));
836236
836352
  }
@@ -836301,7 +836417,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836301
836417
  const { func, envId, force, codeSecret, access, deployMode, functionRootPath, functionPath, yes, log, preCheckResult } = options;
836302
836418
  let finalFunc = Object.assign({}, func);
836303
836419
  if (deployMode === 'image') {
836304
- const fileImageConfig = (0, function_2.buildImageConfigFromConfig)(func);
836420
+ const fileImageConfig = buildImageConfig(func);
836305
836421
  if (fileImageConfig) {
836306
836422
  finalFunc.imageConfig = fileImageConfig;
836307
836423
  }
@@ -836311,7 +836427,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836311
836427
  }
836312
836428
  if (finalFunc.type === 'HTTP' && deployMode !== 'image') {
836313
836429
  const funcPath = functionPath === '.' ? process.cwd() : (functionPath || path_1.default.join(functionRootPath, finalFunc.name));
836314
- const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, finalFunc);
836430
+ const shouldContinue = yield checkWebFunctionBootstrap(funcPath, finalFunc);
836315
836431
  if (!shouldContinue) {
836316
836432
  return;
836317
836433
  }
@@ -836466,7 +836582,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836466
836582
  funcWithType = Object.assign(Object.assign({}, funcWithType), { type: 'HTTP', protocolType: 'WS' });
836467
836583
  }
836468
836584
  if (deployMode === 'image') {
836469
- const fileImageConfig = (0, function_2.buildImageConfigFromConfig)(funcWithType);
836585
+ const fileImageConfig = buildImageConfig(funcWithType);
836470
836586
  if (fileImageConfig) {
836471
836587
  funcWithType = Object.assign(Object.assign({}, funcWithType), { imageConfig: fileImageConfig });
836472
836588
  }
@@ -836475,21 +836591,24 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836475
836591
  return { status: 'skipped', name: func.name };
836476
836592
  }
836477
836593
  }
836478
- const funcPath = func.dir
836479
- ? path_1.default.resolve(process.cwd(), func.dir)
836480
- : path_1.default.join(functionRootPath, func.name);
836594
+ const funcPath = resolveFunctionPath({
836595
+ functionRootPath,
836596
+ functionName: func.name,
836597
+ functionDirFromConfig: func.dir
836598
+ });
836481
836599
  if (deployMode !== 'image' && !fs_1.default.existsSync(funcPath)) {
836482
836600
  log.error((0, i18n_1.t)('未找到函数 [{{name}}] 的目录:{{path}},已跳过', { name: func.name, path: funcPath }));
836483
836601
  return { status: 'skipped', name: func.name };
836484
836602
  }
836485
836603
  if (funcWithType.type === 'HTTP' && deployMode !== 'image') {
836486
- const shouldContinue = yield (0, function_1.checkAndCreateBootstrap)(funcPath, funcWithType);
836604
+ const shouldContinue = yield checkWebFunctionBootstrap(funcPath, funcWithType);
836487
836605
  if (!shouldContinue) {
836488
836606
  log.warn((0, i18n_1.t)('[{{name}}] 已跳过部署', { name: func.name }));
836489
836607
  return { status: 'skipped', name: func.name };
836490
836608
  }
836491
836609
  }
836492
836610
  loading.start((0, i18n_1.t)('云函数部署中'));
836611
+ let deployError = null;
836493
836612
  try {
836494
836613
  yield (0, function_1.createFunction)({
836495
836614
  func: funcWithType,
@@ -836505,32 +836624,33 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836505
836624
  return { status: 'success', name: func.name };
836506
836625
  }
836507
836626
  catch (e) {
836627
+ deployError = e;
836508
836628
  loading.stop();
836509
- try {
836510
- const result = yield this.handleDeployFail(e, {
836511
- func: funcWithType,
836512
- envId,
836513
- force,
836514
- codeSecret,
836515
- functionRootPath,
836516
- functionPath: func.dir ? funcPath : undefined,
836517
- accessPath: access,
836518
- yes: yes || force || functionsToOverwrite.has(func.name),
836519
- batchMode: true,
836520
- logger: log,
836521
- deployMode
836522
- });
836523
- return { status: result || 'error', name: func.name };
836524
- }
836525
- catch (handleError) {
836526
- return { status: 'error', name: func.name, error: handleError };
836527
- }
836629
+ }
836630
+ try {
836631
+ const result = yield this.handleDeployFail(deployError, {
836632
+ func: funcWithType,
836633
+ envId,
836634
+ force,
836635
+ codeSecret,
836636
+ functionRootPath,
836637
+ functionPath: func.dir ? funcPath : undefined,
836638
+ accessPath: access,
836639
+ yes: yes || force || functionsToOverwrite.has(func.name),
836640
+ batchMode: true,
836641
+ logger: log,
836642
+ deployMode
836643
+ });
836644
+ return { status: result || 'error', name: func.name };
836645
+ }
836646
+ catch (handleError) {
836647
+ return { status: 'error', name: func.name, error: handleError };
836528
836648
  }
836529
836649
  }));
836530
836650
  if (tasks.length > 5) {
836531
836651
  log.info((0, i18n_1.t)('函数数量较多,将使用队列部署'));
836532
836652
  }
836533
- const asyncTaskController = new utils_1.AsyncTaskParallelController(5, 50);
836653
+ const asyncTaskController = new utils_1.AsyncTaskParallelController(MAX_PARALLEL_DEPLOY, 50);
836534
836654
  asyncTaskController.loadTasks(tasks);
836535
836655
  const rawResults = yield asyncTaskController.run();
836536
836656
  const results = rawResults.map((r, index) => {
@@ -836621,7 +836741,7 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836621
836741
  }
836622
836742
  const conflicts = this.detectConfigConflicts(func, existingFunction);
836623
836743
  if (conflicts.length > 0) {
836624
- this.displayConfigConflicts(func.name, conflicts);
836744
+ this.displayConfigConflicts(func.name, conflicts, log);
836625
836745
  return 'error';
836626
836746
  }
836627
836747
  func = this.mergeCloudAndLocalConfig(existingFunction, func);
@@ -836966,7 +837086,22 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
836966
837086
  }
836967
837087
  }
836968
837088
  getSpecificSuggestions(error, context = {}) {
837089
+ var _a, _b;
836969
837090
  const { functionName } = context;
837091
+ if (((_a = error.message) === null || _a === void 0 ? void 0 : _a.includes('COS 上传失败')) || ((_b = error.message) === null || _b === void 0 ? void 0 : _b.includes('上传失败'))) {
837092
+ const suggestions = [(0, i18n_1.t)('检查网络连接是否正常')];
837093
+ if (error.code === 'AccessDenied') {
837094
+ suggestions.push((0, i18n_1.t)('签名或权限不正确,拒绝访问'));
837095
+ suggestions.push((0, i18n_1.t)('运行 {{command}} 重新登录', { command: (0, utils_1.highlightCommand)('tcb login') }));
837096
+ }
837097
+ else if (error.code === 'NoSuchBucket') {
837098
+ suggestions.push((0, i18n_1.t)('指定的存储桶不存在,请检查环境配置'));
837099
+ }
837100
+ else if (error.code === 'RequestTimeout') {
837101
+ suggestions.push((0, i18n_1.t)('请求超时,可能是文件过大或网络不稳定'));
837102
+ }
837103
+ return suggestions;
837104
+ }
836970
837105
  if (error.code === 'Forbidden' || error.code === 'Unauthorized' ||
836971
837106
  error.code === 'AuthFailure' || error.code === 'UnauthorizedOperation') {
836972
837107
  return [
@@ -837029,33 +837164,35 @@ let FunctionDeploy = class FunctionDeploy extends common_1.Command {
837029
837164
  }
837030
837165
  });
837031
837166
  }
837032
- displayConfigConflicts(functionName, conflicts) {
837033
- utils_1.logger.error((0, i18n_1.t)('函数 [{{name}}] 存在配置冲突:', { name: functionName }));
837167
+ displayConfigConflicts(functionName, conflicts, log) {
837168
+ const activeLogger = log || utils_1.logger;
837169
+ activeLogger.error((0, i18n_1.t)('函数 [{{name}}] 存在配置冲突:', { name: functionName }));
837034
837170
  conflicts.forEach((conflict) => {
837035
- utils_1.logger.error(` ✗ ${conflict.field}: 云端 ${conflict.cloudValue} ≠ 本地 ${conflict.localValue}`);
837036
- utils_1.logger.error(` ${conflict.message}`);
837171
+ activeLogger.error(` ✗ ${conflict.field}: 云端 ${conflict.cloudValue} ≠ 本地 ${conflict.localValue}`);
837172
+ activeLogger.error(` ${conflict.message}`);
837037
837173
  });
837038
- utils_1.logger.info((0, i18n_1.t)('解决建议:'));
837039
- utils_1.logger.info((0, i18n_1.t)(' 1. 修改本地配置使其与云端一致'));
837040
- utils_1.logger.info((0, i18n_1.t)(' 2. 删除云端函数后重新创建'));
837041
- utils_1.logger.info((0, i18n_1.t)(' 3. 使用 {{command}} 查看云端配置', {
837174
+ activeLogger.info((0, i18n_1.t)('解决建议:'));
837175
+ activeLogger.info((0, i18n_1.t)(' 1. 修改本地配置使其与云端一致'));
837176
+ activeLogger.info((0, i18n_1.t)(' 2. 删除云端函数后重新创建'));
837177
+ activeLogger.info((0, i18n_1.t)(' 3. 使用 {{command}} 查看云端配置', {
837042
837178
  command: (0, utils_1.highlightCommand)(`tcb fn detail ${functionName}`)
837043
837179
  }));
837044
837180
  }
837045
- displayMergedConfig(functionName, config, source) {
837046
- utils_1.logger.info((0, i18n_1.t)('函数 [{{name}}] 最终配置:', { name: functionName }));
837047
- utils_1.logger.info(` ${(0, i18n_1.t)('类型')}: ${config.type || 'Event'}`);
837048
- utils_1.logger.info(` ${(0, i18n_1.t)('运行时')}: ${config.runtime}`);
837049
- utils_1.logger.info(` ${(0, i18n_1.t)('入口')}: ${config.handler}`);
837181
+ displayMergedConfig(functionName, config, source, log) {
837182
+ const activeLogger = log || utils_1.logger;
837183
+ activeLogger.info((0, i18n_1.t)('函数 [{{name}}] 最终配置:', { name: functionName }));
837184
+ activeLogger.info(` ${(0, i18n_1.t)('类型')}: ${config.type || 'Event'}`);
837185
+ activeLogger.info(` ${(0, i18n_1.t)('运行时')}: ${config.runtime}`);
837186
+ activeLogger.info(` ${(0, i18n_1.t)('入口')}: ${config.handler}`);
837050
837187
  if (config.memorySize) {
837051
- utils_1.logger.info(` ${(0, i18n_1.t)('内存')}: ${config.memorySize}MB`);
837188
+ activeLogger.info(` ${(0, i18n_1.t)('内存')}: ${config.memorySize}MB`);
837052
837189
  }
837053
- utils_1.logger.info(` ${(0, i18n_1.t)('超时')}: ${config.timeout}s`);
837190
+ activeLogger.info(` ${(0, i18n_1.t)('超时')}: ${config.timeout}s`);
837054
837191
  if (source === 'inferred') {
837055
- utils_1.logger.info((0, i18n_1.t)(' (配置来源: 智能推测)'));
837192
+ activeLogger.info((0, i18n_1.t)(' (配置来源: 智能推测)'));
837056
837193
  }
837057
837194
  else if (source === 'default') {
837058
- utils_1.logger.info((0, i18n_1.t)(' (配置来源: 默认配置)'));
837195
+ activeLogger.info((0, i18n_1.t)(' (配置来源: 默认配置)'));
837059
837196
  }
837060
837197
  }
837061
837198
  confirmUpdate(functionName) {
@@ -901898,117 +902035,213 @@ function isNodeFunction(runtime) {
901898
902035
  /**
901899
902036
  * 构建镜像配置对象
901900
902037
  * @param imageConfig 镜像配置
901901
- * @param options 可选配置
901902
- * @param options.includeCommandList 是否包含 CommandList/ArgsList(仅 CreateFunction 支持)
901903
902038
  * @returns 构建好的镜像配置对象
901904
902039
  */
901905
- function buildImageConfig(imageConfig, options) {
901906
- var _a, _b;
901907
- const { includeCommandList = false } = options || {};
901908
- const config = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ ImageType: imageConfig.imageType || 'enterprise', ImageUri: imageConfig.imageUri }, (imageConfig.registryId && { RegistryId: imageConfig.registryId })), (imageConfig.entryPoint && { EntryPoint: imageConfig.entryPoint })), (imageConfig.command && { Command: imageConfig.command })), (imageConfig.args && { Args: imageConfig.args })), (typeof imageConfig.containerImageAccelerate === 'boolean' && {
901909
- ContainerImageAccelerate: imageConfig.containerImageAccelerate
901910
- })), { ImagePort: imageConfig.imagePort || 9000 });
901911
- // CommandList 和 ArgsList 仅在 CreateFunction 时支持
901912
- if (includeCommandList) {
901913
- if ((_a = imageConfig.commandList) === null || _a === void 0 ? void 0 : _a.length) {
901914
- config.CommandList = imageConfig.commandList;
901915
- }
901916
- if ((_b = imageConfig.argsList) === null || _b === void 0 ? void 0 : _b.length) {
901917
- config.ArgsList = imageConfig.argsList;
902040
+ function buildImageConfig(imageConfig) {
902041
+ // 先转换大小写
902042
+ const config = toPascalCaseKeys(imageConfig);
902043
+ // 再补充默认值
902044
+ return Object.assign({ ImageType: 'enterprise', ImagePort: 9000 }, config);
902045
+ }
902046
+ /**
902047
+ * 递归转换对象的 key 从 camelCase 到 PascalCase
902048
+ */
902049
+ function toPascalCaseKeys(obj) {
902050
+ if (obj === null || obj === undefined)
902051
+ return obj;
902052
+ if (Array.isArray(obj))
902053
+ return obj.map(item => toPascalCaseKeys(item));
902054
+ if (typeof obj !== 'object')
902055
+ return obj;
902056
+ const result = {};
902057
+ for (const key of Object.keys(obj)) {
902058
+ // 通用规则:首字母大写
902059
+ const pascalKey = key.charAt(0).toUpperCase() + key.slice(1);
902060
+ result[pascalKey] = toPascalCaseKeys(obj[key]);
902061
+ }
902062
+ return result;
902063
+ }
902064
+ /**
902065
+ * 将布尔值转换为 API 需要的 'TRUE'/'FALSE' 字符串
902066
+ * 支持 boolean | string | undefined 输入
902067
+ * @param value 输入值
902068
+ * @returns 'TRUE' | 'FALSE' | undefined
902069
+ */
902070
+ function toBooleanString(value) {
902071
+ if (value === undefined)
902072
+ return undefined;
902073
+ // 已经是字符串格式
902074
+ if (value === 'TRUE' || value === 'FALSE')
902075
+ return value;
902076
+ // 字符串 'true'/'false' 兼容
902077
+ if (typeof value === 'string') {
902078
+ return value.toUpperCase() === 'TRUE' ? 'TRUE' : 'FALSE';
902079
+ }
902080
+ // 布尔值转换
902081
+ return value ? 'TRUE' : 'FALSE';
902082
+ }
902083
+ /**
902084
+ * 大小写不敏感获取对象字段值(优先 camelCase)
902085
+ * @param obj 目标对象
902086
+ * @param fieldName 字段名(任意大小写)
902087
+ * @returns 字段值,找不到返回 undefined
902088
+ * @example
902089
+ * getFieldIgnoreCase({ type: 'A', Type: 'B' }, 'type') // → 'A' (camelCase 优先)
902090
+ * getFieldIgnoreCase({ Type: 'B' }, 'type') // → 'B'
902091
+ */
902092
+ function getFieldIgnoreCase(obj, fieldName) {
902093
+ if (!obj || typeof obj !== 'object')
902094
+ return undefined;
902095
+ const lowerFieldName = fieldName.toLowerCase();
902096
+ // 优先查找 camelCase(首字母小写)
902097
+ const camelCaseKey = lowerFieldName.charAt(0).toLowerCase() + fieldName.slice(1);
902098
+ if (obj[camelCaseKey] !== undefined) {
902099
+ return obj[camelCaseKey];
902100
+ }
902101
+ // 其次查找 PascalCase(首字母大写)
902102
+ const pascalCaseKey = lowerFieldName.charAt(0).toUpperCase() + fieldName.slice(1);
902103
+ if (obj[pascalCaseKey] !== undefined) {
902104
+ return obj[pascalCaseKey];
902105
+ }
902106
+ // 最后遍历查找任意大小写匹配
902107
+ for (const key of Object.keys(obj)) {
902108
+ if (key.toLowerCase() === lowerFieldName) {
902109
+ return obj[key];
901918
902110
  }
901919
902111
  }
901920
- return config;
902112
+ return undefined;
901921
902113
  }
901922
- // 解析函数配置,换成请求参数
902114
+ // 解析函数配置,换成请求参数(用于 CreateFunction)
901923
902115
  function configToParams(options) {
901924
- var _a, _b, _c, _d, _e, _f, _g;
901925
- const { func, codeSecret, baseParams } = options;
901926
- let installDependency;
901927
- // Node 函数默认安装依赖
901928
- installDependency = isNodeFunction(func.runtime) ? 'TRUE' : 'FALSE';
901929
- // 是否安装依赖,选项可以覆盖
901930
- if (typeof func.installDependency !== 'undefined') {
901931
- installDependency = func.installDependency ? 'TRUE' : 'FALSE';
902116
+ var _a, _b, _c;
902117
+ const { func, codeSecret, baseParams = {} } = options;
902118
+ // 白名单:只有这些字段会被透传到 API(大小写不敏感)
902119
+ // 参考 SCF API 文档:https://cloud.tencent.com/document/product/583/18586
902120
+ // key: 小写用于匹配,value: PascalCase 用于输出
902121
+ const AUTO_CONVERT_FIELDS = {
902122
+ // 基础配置
902123
+ 'description': 'Description',
902124
+ 'memorysize': 'MemorySize',
902125
+ 'timeout': 'Timeout',
902126
+ 'runtime': 'Runtime',
902127
+ 'type': 'Type', // Event/HTTP
902128
+ 'role': 'Role',
902129
+ // 日志配置
902130
+ 'clslogsetid': 'ClsLogsetId',
902131
+ 'clstopicid': 'ClsTopicId',
902132
+ // 高级配置
902133
+ 'deadletterconfig': 'DeadLetterConfig',
902134
+ 'publicnetconfig': 'PublicNetConfig',
902135
+ 'cfsconfig': 'CfsConfig',
902136
+ 'inittimeout': 'InitTimeout',
902137
+ 'tags': 'Tags',
902138
+ // 注意:asyncRunEnable/traceEnable/autoDeployClsTopicIndex/autoCreateClsTopic/dnsCache
902139
+ // 需要 'TRUE'/'FALSE' 字符串,在特殊处理阶段处理
902140
+ 'protocoltype': 'ProtocolType', // WS
902141
+ 'intranetconfig': 'IntranetConfig',
902142
+ };
902143
+ let params = Object.assign(Object.assign({}, baseParams), { FunctionName: func.name });
902144
+ // 第一阶段:白名单字段自动转换(大小写不敏感,统一输出 PascalCase)
902145
+ for (const key of Object.keys(func)) {
902146
+ const lowerKey = key.toLowerCase();
902147
+ const pascalKey = AUTO_CONVERT_FIELDS[lowerKey];
902148
+ if (!pascalKey || func[key] === undefined)
902149
+ continue;
902150
+ params[pascalKey] = toPascalCaseKeys(func[key]);
901932
902151
  }
901933
- // 转换环境变量
901934
- const envVariables = Object.keys(func.envVariables || {}).map(key => ({
901935
- Key: key,
901936
- Value: func.envVariables[key]
901937
- }));
901938
- // 当不存在 L5 配置时,不修改 L5 状态,否则根据 true/false 进行修改
901939
- const l5Enable = typeof (func === null || func === void 0 ? void 0 : func.l5) === 'undefined' ? null : (func === null || func === void 0 ? void 0 : func.l5) ? 'TRUE' : 'FALSE';
901940
- const params = Object.assign(Object.assign({}, baseParams), { FunctionName: func.name,
901941
- // 不可选择
901942
- L5Enable: l5Enable });
901943
- // 函数绑定的角色
901944
- params.Role = func.role || params.Role;
901945
- // 修复参数存在 undefined 字段时,会出现鉴权失败的情况
901946
- // Environment 为覆盖式修改,不保留已有字段
901947
- envVariables.length && (params.Environment = { Variables: envVariables });
901948
- // 处理入口
901949
- params.Handler = func.handler || 'index.main';
901950
- // 默认超时时间为 10S
901951
- params.Timeout = Number(func.timeout) || 10;
901952
- // 默认运行环境 Nodejs8.9
901953
- params.Runtime = func.runtime || 'Nodejs8.9';
902152
+ // 第二阶段:特殊处理字段
902153
+ // 1. 安装依赖标志(支持 boolean | string)
902154
+ if (func.installDependency !== undefined) {
902155
+ params.InstallDependency = toBooleanString(func.installDependency);
902156
+ }
902157
+ // 2. L5 配置 - 当不存在时不修改,否则根据 true/false 进行修改
902158
+ if (func.l5 !== undefined) {
902159
+ params.L5Enable = toBooleanString(func.l5);
902160
+ }
902161
+ else {
902162
+ params.L5Enable = null;
902163
+ }
902164
+ // 3. 需要 'TRUE'/'FALSE' 字符串的布尔字段统一处理(大小写不敏感)
902165
+ // key: 小写用于匹配,value: PascalCase 用于输出
902166
+ const BOOLEAN_STRING_FIELDS = {
902167
+ 'asyncrunenable': 'AsyncRunEnable', // 异步属性
902168
+ 'traceenable': 'TraceEnable', // 事件追踪
902169
+ 'autodeployclstopicindex': 'AutoDeployClsTopicIndex', // 自动创建 CLS 索引
902170
+ 'autocreateclstopic': 'AutoCreateClsTopic', // 自动创建 CLS 主题
902171
+ 'dnscache': 'DnsCache', // Dns 缓存
902172
+ };
902173
+ for (const key of Object.keys(func)) {
902174
+ const lowerKey = key.toLowerCase();
902175
+ const pascalKey = BOOLEAN_STRING_FIELDS[lowerKey];
902176
+ if (pascalKey && func[key] !== undefined) {
902177
+ params[pascalKey] = toBooleanString(func[key]);
902178
+ }
902179
+ }
902180
+ // 5. 环境变量 - 为覆盖式修改,不保留已有字段
902181
+ if (func.envVariables && Object.keys(func.envVariables).length > 0) {
902182
+ params.Environment = {
902183
+ Variables: Object.keys(func.envVariables).map(key => ({
902184
+ Key: key,
902185
+ Value: func.envVariables[key]
902186
+ }))
902187
+ };
902188
+ }
902189
+ // 4. 函数角色(如果白名单已处理则跳过)
902190
+ if (!params.Role && func.role) {
902191
+ params.Role = func.role;
902192
+ }
902193
+ // 5. VPC 配置
901954
902194
  if (((_a = func === null || func === void 0 ? void 0 : func.vpc) === null || _a === void 0 ? void 0 : _a.subnetId) !== undefined && ((_b = func === null || func === void 0 ? void 0 : func.vpc) === null || _b === void 0 ? void 0 : _b.vpcId) !== undefined) {
901955
- // VPC 网络
901956
902195
  params.VpcConfig = {
901957
- SubnetId: (_c = func === null || func === void 0 ? void 0 : func.vpc) === null || _c === void 0 ? void 0 : _c.subnetId,
901958
- VpcId: (_d = func === null || func === void 0 ? void 0 : func.vpc) === null || _d === void 0 ? void 0 : _d.vpcId
902196
+ SubnetId: func.vpc.subnetId,
902197
+ VpcId: func.vpc.vpcId
901959
902198
  };
901960
902199
  }
901961
- // 运行内存
901962
- params.MemorySize = func.memorySize || 256;
901963
- // 自动安装依赖
901964
- params.InstallDependency = installDependency;
901965
- // 代码保护
901966
- if (codeSecret || func.codeSecret) {
901967
- params.CodeSecret = codeSecret || func.codeSecret;
901968
- }
901969
- // 函数层
901970
- if ((_e = func === null || func === void 0 ? void 0 : func.layers) === null || _e === void 0 ? void 0 : _e.length) {
901971
- const transformLayers = func.layers.map(item => ({
902200
+ // 6. 函数层
902201
+ if ((_c = func === null || func === void 0 ? void 0 : func.layers) === null || _c === void 0 ? void 0 : _c.length) {
902202
+ params.Layers = func.layers.map(item => ({
901972
902203
  LayerName: item.name,
901973
902204
  LayerVersion: item.version
901974
902205
  }));
901975
- params.Layers = transformLayers;
901976
902206
  }
901977
- // HTTP 云函数类型
901978
- if ((func === null || func === void 0 ? void 0 : func.type) === 'HTTP') {
901979
- params.Type = 'HTTP';
901980
- // WebSocket 协议支持
901981
- if ((func === null || func === void 0 ? void 0 : func.protocolType) === 'WS') {
901982
- params.ProtocolType = 'WS';
901983
- // 协议参数,直接透传或使用默认值
901984
- // 参考文档:https://cloud.tencent.com/document/api/583/17244#ProtocolParams
901985
- const idleTimeOut = (_g = (_f = func === null || func === void 0 ? void 0 : func.protocolParams) === null || _f === void 0 ? void 0 : _f.wsParams) === null || _g === void 0 ? void 0 : _g.idleTimeOut;
902207
+ // 7. 代码保护
902208
+ if (codeSecret || func.codeSecret) {
902209
+ params.CodeSecret = codeSecret || func.codeSecret;
902210
+ }
902211
+ // 8. 协议参数(WebSocket,大小写不敏感)
902212
+ const protocolParams = getFieldIgnoreCase(func, 'protocolParams');
902213
+ if (protocolParams) {
902214
+ const wsParams = getFieldIgnoreCase(protocolParams, 'wsParams');
902215
+ if (wsParams) {
901986
902216
  params.ProtocolParams = {
901987
- WSParams: {
901988
- IdleTimeOut: typeof idleTimeOut === 'number' ? idleTimeOut : 15
901989
- }
901990
- };
901991
- }
901992
- // 多并发配置
901993
- // 参考文档:https://cloud.tencent.com/document/api/583/17244#InstanceConcurrencyConfig
901994
- if (func === null || func === void 0 ? void 0 : func.instanceConcurrencyConfig) {
901995
- params.InstanceConcurrencyConfig = {
901996
- DynamicEnabled: func.instanceConcurrencyConfig.dynamicEnabled || 'FALSE',
901997
- MaxConcurrency: func.instanceConcurrencyConfig.maxConcurrency || 10
902217
+ WSParams: toPascalCaseKeys(wsParams)
901998
902218
  };
901999
902219
  }
902000
902220
  }
902001
- // 云函数描述
902002
- if (func === null || func === void 0 ? void 0 : func.description) {
902003
- params.Description = func.description;
902221
+ // 9. HTTP 云函数特殊处理(type 字段大小写不敏感)
902222
+ const funcType = getFieldIgnoreCase(func, 'type');
902223
+ if ((funcType === null || funcType === void 0 ? void 0 : funcType.toUpperCase()) === 'HTTP') {
902224
+ params.Type = 'HTTP';
902225
+ // 多并发配置 - 仅 HTTP 函数支持(大小写不敏感)
902226
+ const instanceConcurrencyConfig = getFieldIgnoreCase(func, 'instanceConcurrencyConfig');
902227
+ if (instanceConcurrencyConfig) {
902228
+ const config = toPascalCaseKeys(instanceConcurrencyConfig);
902229
+ // DynamicEnabled 需要特殊处理为 'TRUE'/'FALSE'
902230
+ if (config.DynamicEnabled !== undefined) {
902231
+ config.DynamicEnabled = toBooleanString(config.DynamicEnabled);
902232
+ }
902233
+ params.InstanceConcurrencyConfig = config;
902234
+ }
902004
902235
  }
902005
- // 镜像配置(用于镜像部署)
902006
- if (func === null || func === void 0 ? void 0 : func.imageConfig) {
902007
- params.Code = {
902008
- ImageConfig: buildImageConfig(func.imageConfig, { includeCommandList: true })
902009
- };
902236
+ // 10. 镜像配置(用于镜像部署,大小写不敏感)
902237
+ const imageConfig = getFieldIgnoreCase(func, 'imageConfig');
902238
+ if (imageConfig) {
902239
+ params.Code = params.Code || {};
902240
+ params.Code.ImageConfig = buildImageConfig(imageConfig);
902010
902241
  }
902011
- return params;
902242
+ // 第三阶段:统一应用默认值
902243
+ const runtime = params.Runtime || 'Nodejs18.15';
902244
+ return Object.assign({ Handler: func.handler || 'index.main', Timeout: 10, Runtime: 'Nodejs18.15', MemorySize: 256, InstallDependency: isNodeFunction(runtime) ? 'TRUE' : 'FALSE' }, params);
902012
902245
  }
902013
902246
  class FunctionService {
902014
902247
  constructor(environment) {
@@ -902025,12 +902258,11 @@ class FunctionService {
902025
902258
  * @memberof FunctionService
902026
902259
  */
902027
902260
  async updateFunctionIncrementalCode(funcParam) {
902028
- const { env, namespace } = this.getFunctionConfig();
902261
+ const { namespace } = this.getFunctionConfig();
902029
902262
  const { functionRootPath, func, deleteFiles, addFiles } = funcParam;
902030
902263
  const { name, runtime } = func;
902031
902264
  const params = {
902032
902265
  FunctionName: name,
902033
- EnvId: env,
902034
902266
  Namespace: namespace
902035
902267
  };
902036
902268
  let packer;
@@ -902055,7 +902287,7 @@ class FunctionService {
902055
902287
  }
902056
902288
  params.AddFiles = base64;
902057
902289
  }
902058
- return this.tcbService.request('UpdateFunctionIncrementalCode', params);
902290
+ return this.scfService.request('UpdateFunctionIncrementalCode', params);
902059
902291
  }
902060
902292
  /**
902061
902293
  * 创建云函数
@@ -902063,25 +902295,28 @@ class FunctionService {
902063
902295
  * @returns {(Promise<IResponseInfo | ICreateFunctionRes>)}
902064
902296
  */
902065
902297
  async createFunction(funcParam) {
902066
- var _a;
902067
- const { env } = this.getFunctionConfig();
902298
+ var _a, _b, _c;
902299
+ const { namespace } = this.getFunctionConfig();
902068
902300
  const { func, functionRootPath, force = false, base64Code, codeSecret, functionPath, deployMode } = funcParam;
902069
902301
  const funcName = func.name;
902302
+ const { TopicId, LogsetId } = this.getClsServiceConfig();
902070
902303
  const params = configToParams({
902071
902304
  func,
902072
902305
  codeSecret,
902073
902306
  baseParams: {
902074
- EnvId: env,
902307
+ Namespace: namespace,
902075
902308
  Role: 'TCB_QcsRole',
902076
- Stamp: 'MINI_QCBASE'
902309
+ Stamp: 'MINI_QCBASE',
902310
+ ClsTopicId: TopicId,
902311
+ ClsLogsetId: LogsetId
902077
902312
  }
902078
902313
  });
902079
902314
  // 根据部署方式处理 Code 参数
902080
902315
  // 优先使用显式指定的 deployMode,如果未指定但存在 imageConfig 则认为是镜像部署
902081
- const isImageDeploy = deployMode === 'image' || (!deployMode && func.imageConfig);
902316
+ const isImageDeploy = deployMode === 'image' || (!deployMode && ((_a = params.Code) === null || _a === void 0 ? void 0 : _a.ImageConfig));
902082
902317
  if (isImageDeploy) {
902083
902318
  // 镜像部署:Code 参数已在 configToParams 中通过 imageConfig 设置
902084
- if (!((_a = func.imageConfig) === null || _a === void 0 ? void 0 : _a.imageUri)) {
902319
+ if (!((_c = (_b = params.Code) === null || _b === void 0 ? void 0 : _b.ImageConfig) === null || _c === void 0 ? void 0 : _c.ImageUri)) {
902085
902320
  throw new error_1.CloudBaseError('镜像部署需要配置 imageConfig.imageUri');
902086
902321
  }
902087
902322
  // 镜像部署的特殊配置
@@ -902100,12 +902335,9 @@ class FunctionService {
902100
902335
  deployMode
902101
902336
  }, params.InstallDependency);
902102
902337
  }
902103
- const { TopicId, LogsetId } = this.getClsServiceConfig();
902104
- params.ClsTopicId = TopicId;
902105
- params.ClsLogsetId = LogsetId;
902106
902338
  try {
902107
902339
  // 创建云函数
902108
- const res = await this.tcbService.request('CreateFunction', params);
902340
+ const res = await this.scfService.request('CreateFunction', params);
902109
902341
  // 等待函数状态正常
902110
902342
  await this.waitFunctionActive(funcName, codeSecret);
902111
902343
  // 创建函数触发器、失败自动重试
@@ -902175,9 +902407,9 @@ class FunctionService {
902175
902407
  */
902176
902408
  async getFunctionList(limit = 20, offset = 0) {
902177
902409
  // 获取Function 环境配置
902178
- const { env } = this.getFunctionConfig();
902179
- const res = await this.tcbService.request('ListFunctions', {
902180
- EnvId: env,
902410
+ const { namespace } = this.getFunctionConfig();
902411
+ const res = await this.scfService.request('ListFunctions', {
902412
+ Namespace: namespace,
902181
902413
  Limit: limit,
902182
902414
  Offset: offset
902183
902415
  });
@@ -902191,9 +902423,9 @@ class FunctionService {
902191
902423
  */
902192
902424
  async listFunctions(limit = 20, offset = 0) {
902193
902425
  // 获取Function 环境配置
902194
- const { env } = this.getFunctionConfig();
902195
- const res = await this.tcbService.request('ListFunctions', {
902196
- EnvId: env,
902426
+ const { namespace } = this.getFunctionConfig();
902427
+ const res = await this.scfService.request('ListFunctions', {
902428
+ Namespace: namespace,
902197
902429
  Limit: limit,
902198
902430
  Offset: offset
902199
902431
  });
@@ -902224,8 +902456,8 @@ class FunctionService {
902224
902456
  const { envId } = options;
902225
902457
  while (true) {
902226
902458
  try {
902227
- const res = await this.tcbService.request('ListFunctions', {
902228
- EnvId: envId,
902459
+ const res = await this.scfService.request('ListFunctions', {
902460
+ Namespace: envId,
902229
902461
  Limit: pageSize,
902230
902462
  Offset: currentOffset
902231
902463
  });
@@ -902265,22 +902497,25 @@ class FunctionService {
902265
902497
  * @param {string} qualifier 需要删除的版本号,不填默认删除函数下全部版本。
902266
902498
  * @returns {Promise<IResponseInfo>}
902267
902499
  */
902268
- async deleteFunction({ name }) {
902500
+ async deleteFunction(name) {
902269
902501
  var _a;
902502
+ const funcName = typeof name === 'string'
902503
+ ? name
902504
+ : name === null || name === void 0 ? void 0 : name.name;
902270
902505
  const { namespace } = this.getFunctionConfig();
902271
902506
  // 检测是否绑定了 API 网关
902272
902507
  const accessService = this.environment.getAccessService();
902273
902508
  const res = await accessService.getAccessList({
902274
- name
902509
+ name: funcName
902275
902510
  });
902276
902511
  // 删除绑定的 API 网关
902277
902512
  if (((_a = res === null || res === void 0 ? void 0 : res.APISet) === null || _a === void 0 ? void 0 : _a.length) > 0) {
902278
902513
  await accessService.deleteAccess({
902279
- name
902514
+ name: funcName
902280
902515
  });
902281
902516
  }
902282
- await this.scfService.request('DeleteFunction', {
902283
- FunctionName: name,
902517
+ return await this.scfService.request('DeleteFunction', {
902518
+ FunctionName: funcName,
902284
902519
  Namespace: namespace
902285
902520
  });
902286
902521
  }
@@ -902308,17 +902543,16 @@ class FunctionService {
902308
902543
  * @returns {Promise<Record<string, string>>}
902309
902544
  */
902310
902545
  async getFunctionDetail(name, codeSecret) {
902311
- const { env } = this.getFunctionConfig();
902546
+ const { namespace } = this.getFunctionConfig();
902312
902547
  const params = {
902313
902548
  FunctionName: name,
902314
- EnvId: env,
902315
902549
  ShowCode: 'TRUE',
902316
- Namespace: env
902550
+ Namespace: namespace
902317
902551
  };
902318
902552
  if (codeSecret) {
902319
902553
  params.CodeSecret = codeSecret;
902320
902554
  }
902321
- const data = await this.tcbService.request('GetFunction', params);
902555
+ const data = await this.scfService.request('GetFunction', params);
902322
902556
  // 解析 VPC 配置
902323
902557
  const { VpcId = '', SubnetId = '' } = data.VpcConfig || {};
902324
902558
  if (VpcId && SubnetId) {
@@ -902495,67 +902729,113 @@ class FunctionService {
902495
902729
  * @returns {Promise<IResponseInfo>}
902496
902730
  */
902497
902731
  async updateFunctionConfig(func) {
902498
- var _a, _b, _c, _d, _e, _f, _g;
902732
+ var _a, _b, _c;
902499
902733
  const { namespace } = this.getFunctionConfig();
902500
- const envVariables = Object.keys(func.envVariables || {}).map(key => ({
902501
- Key: key,
902502
- Value: func.envVariables[key]
902503
- }));
902504
- // 当不存在 L5 配置时,不修改 L5 状态,否则根据 true/false 进行修改
902505
- const l5Enable = typeof func.l5 === 'undefined' ? null : func.l5 ? 'TRUE' : 'FALSE';
902734
+ // UpdateFunctionConfiguration API 白名单(大小写不敏感)
902735
+ // 参考:https://cloud.tencent.com/document/product/583/18580
902736
+ // 注意:Runtime, Handler, Code, Type, ProtocolType 只能在 CreateFunction 时指定
902737
+ // key: 小写用于匹配,value: PascalCase 用于输出
902738
+ const UPDATE_CONFIG_FIELDS = {
902739
+ 'description': 'Description',
902740
+ 'memorysize': 'MemorySize',
902741
+ 'timeout': 'Timeout',
902742
+ 'role': 'Role',
902743
+ // 日志配置
902744
+ 'clslogsetid': 'ClsLogsetId',
902745
+ 'clstopicid': 'ClsTopicId',
902746
+ // 高级配置
902747
+ 'deadletterconfig': 'DeadLetterConfig',
902748
+ 'publicnetconfig': 'PublicNetConfig',
902749
+ 'cfsconfig': 'CfsConfig',
902750
+ 'inittimeout': 'InitTimeout',
902751
+ // 注意:asyncRunEnable/traceEnable/autoDeployClsTopicIndex/autoCreateClsTopic
902752
+ // 只能在 CreateFunction 时设置,UpdateFunctionConfiguration 不支持
902753
+ // 注意:dnsCache 需要 'TRUE'/'FALSE' 字符串,在特殊处理阶段处理
902754
+ 'intranetconfig': 'IntranetConfig',
902755
+ };
902756
+ const { TopicId, LogsetId } = this.getClsServiceConfig();
902757
+ // 构建参数
902506
902758
  const params = {
902507
- FunctionName: func.name,
902508
902759
  Namespace: namespace,
902509
- L5Enable: l5Enable
902510
- };
902511
- if (func === null || func === void 0 ? void 0 : func.description) {
902512
- params.Description = func.description;
902760
+ FunctionName: func.name,
902761
+ ClsTopicId: TopicId,
902762
+ ClsLogsetId: LogsetId
902763
+ };
902764
+ // 白名单字段自动转换(大小写不敏感,统一输出 PascalCase)
902765
+ for (const key of Object.keys(func)) {
902766
+ const lowerKey = key.toLowerCase();
902767
+ const pascalKey = UPDATE_CONFIG_FIELDS[lowerKey];
902768
+ if (!pascalKey || func[key] === undefined)
902769
+ continue;
902770
+ params[pascalKey] = toPascalCaseKeys(func[key]);
902513
902771
  }
902514
- // 修复参数存在 undefined 字段时,会出现鉴权失败的情况
902515
- // Environment 为覆盖式修改,不保留已有字段
902516
- envVariables.length && (params.Environment = { Variables: envVariables });
902517
- // 不设默认超时时间,防止覆盖已有配置
902518
- func.timeout && (params.Timeout = func.timeout);
902519
- // 运行时
902520
- func.runtime && (params.Runtime = func.runtime);
902772
+ // 特殊处理:安装依赖标志(支持 boolean | string)
902773
+ if (func.installDependency !== undefined) {
902774
+ params.InstallDependency = toBooleanString(func.installDependency);
902775
+ }
902776
+ // 特殊处理:L5 配置(支持 boolean | string)
902777
+ if (func.l5 !== undefined) {
902778
+ params.L5Enable = toBooleanString(func.l5);
902779
+ }
902780
+ // 特殊处理:DnsCache(支持 boolean | string,大小写不敏感)
902781
+ // 注意:asyncRunEnable/traceEnable/autoDeployClsTopicIndex/autoCreateClsTopic
902782
+ // 只能在 CreateFunction 时设置,UpdateFunctionConfiguration 不支持这些参数
902783
+ const dnsCacheValue = getFieldIgnoreCase(func, 'dnsCache');
902784
+ if (dnsCacheValue !== undefined) {
902785
+ params.DnsCache = toBooleanString(dnsCacheValue);
902786
+ }
902787
+ // 特殊处理:Publish - 是否同时发布新版本(支持 boolean | string,大小写不敏感)
902788
+ const publishValue = getFieldIgnoreCase(func, 'publish');
902789
+ if (publishValue !== undefined) {
902790
+ params.Publish = toBooleanString(publishValue);
902791
+ }
902792
+ // 特殊处理:环境变量
902793
+ if (func.envVariables && Object.keys(func.envVariables).length > 0) {
902794
+ params.Environment = {
902795
+ Variables: Object.keys(func.envVariables).map(key => ({
902796
+ Key: key,
902797
+ Value: func.envVariables[key]
902798
+ }))
902799
+ };
902800
+ }
902801
+ // 特殊处理:VPC 配置
902521
902802
  if (((_a = func === null || func === void 0 ? void 0 : func.vpc) === null || _a === void 0 ? void 0 : _a.subnetId) !== undefined && ((_b = func === null || func === void 0 ? void 0 : func.vpc) === null || _b === void 0 ? void 0 : _b.vpcId) !== undefined) {
902522
- // VPC 网络
902523
902803
  params.VpcConfig = {
902524
- SubnetId: (_c = func === null || func === void 0 ? void 0 : func.vpc) === null || _c === void 0 ? void 0 : _c.subnetId,
902525
- VpcId: (_d = func === null || func === void 0 ? void 0 : func.vpc) === null || _d === void 0 ? void 0 : _d.vpcId
902804
+ SubnetId: func.vpc.subnetId,
902805
+ VpcId: func.vpc.vpcId
902526
902806
  };
902527
902807
  }
902528
- // 内存
902529
- func.memorySize && (params.MemorySize = func.memorySize);
902530
- // Node 函数默认安装依赖
902531
- isNodeFunction(func.runtime) && (params.InstallDependency = 'TRUE');
902532
- // 是否安装依赖,选项可以覆盖
902533
- if (typeof func.installDependency !== 'undefined') {
902534
- params.InstallDependency = func.installDependency ? 'TRUE' : 'FALSE';
902535
- }
902536
- // 函数层
902537
- if ((_e = func === null || func === void 0 ? void 0 : func.layers) === null || _e === void 0 ? void 0 : _e.length) {
902538
- const transformLayers = func.layers.map(item => ({
902808
+ // 特殊处理:函数层
902809
+ if ((_c = func === null || func === void 0 ? void 0 : func.layers) === null || _c === void 0 ? void 0 : _c.length) {
902810
+ params.Layers = func.layers.map(item => ({
902539
902811
  LayerName: item.name,
902540
902812
  LayerVersion: item.version
902541
902813
  }));
902542
- params.Layers = transformLayers;
902543
902814
  }
902544
- // WebSocket 协议支持(仅 HTTP 函数)
902545
- if (func === null || func === void 0 ? void 0 : func.protocolParams) {
902546
- const idleTimeOut = (_g = (_f = func === null || func === void 0 ? void 0 : func.protocolParams) === null || _f === void 0 ? void 0 : _f.wsParams) === null || _g === void 0 ? void 0 : _g.idleTimeOut;
902547
- params.ProtocolParams = {
902548
- WSParams: {
902549
- IdleTimeOut: typeof idleTimeOut === 'number' ? idleTimeOut : 15
902550
- }
902551
- };
902815
+ // 特殊处理:HTTP 函数多并发配置(大小写不敏感)
902816
+ const instanceConcurrencyConfig = getFieldIgnoreCase(func, 'instanceConcurrencyConfig');
902817
+ if (instanceConcurrencyConfig) {
902818
+ const config = toPascalCaseKeys(instanceConcurrencyConfig);
902819
+ // DynamicEnabled 需要特殊处理为 'TRUE'/'FALSE'
902820
+ if (config.DynamicEnabled !== undefined) {
902821
+ config.DynamicEnabled = toBooleanString(config.DynamicEnabled);
902822
+ }
902823
+ params.InstanceConcurrencyConfig = config;
902824
+ }
902825
+ // 特殊处理:HTTP 函数协议参数(WebSocket,大小写不敏感)
902826
+ const protocolParams = getFieldIgnoreCase(func, 'protocolParams');
902827
+ if (protocolParams) {
902828
+ const wsParams = getFieldIgnoreCase(protocolParams, 'wsParams');
902829
+ if (wsParams) {
902830
+ params.ProtocolParams = {
902831
+ WSParams: toPascalCaseKeys(wsParams)
902832
+ };
902833
+ }
902552
902834
  }
902553
- // 多并发配置(仅 HTTP 函数)
902554
- if (func === null || func === void 0 ? void 0 : func.instanceConcurrencyConfig) {
902555
- params.InstanceConcurrencyConfig = {
902556
- DynamicEnabled: func.instanceConcurrencyConfig.dynamicEnabled || 'FALSE',
902557
- MaxConcurrency: func.instanceConcurrencyConfig.maxConcurrency || 10
902558
- };
902835
+ // 特殊处理:忽略系统日志上报(Boolean 类型,直接传递,大小写不敏感)
902836
+ const ignoreSysLogValue = getFieldIgnoreCase(func, 'ignoreSysLog');
902837
+ if (ignoreSysLogValue !== undefined) {
902838
+ params.IgnoreSysLog = ignoreSysLogValue;
902559
902839
  }
902560
902840
  try {
902561
902841
  // 如果函数配置中包含触发器,则更新触发器
@@ -902584,26 +902864,25 @@ class FunctionService {
902584
902864
  * @memberof FunctionService
902585
902865
  */
902586
902866
  async updateFunctionCode(funcParam) {
902587
- var _a;
902588
902867
  const { func, functionRootPath, base64Code, codeSecret, functionPath, deployMode } = funcParam;
902589
902868
  const funcName = func.name;
902590
- const { env } = this.getFunctionConfig();
902869
+ const { namespace } = this.getFunctionConfig();
902591
902870
  // 镜像部署:使用镜像配置更新函数代码
902592
902871
  if (deployMode === 'image') {
902593
- if (!((_a = func.imageConfig) === null || _a === void 0 ? void 0 : _a.imageUri)) {
902594
- throw new error_1.CloudBaseError('镜像部署需要配置 imageConfig.imageUri');
902595
- }
902596
902872
  const params = {
902597
902873
  FunctionName: funcName,
902598
- EnvId: env,
902874
+ Namespace: namespace,
902599
902875
  Code: {
902600
902876
  ImageConfig: buildImageConfig(func.imageConfig)
902601
902877
  }
902602
902878
  };
902879
+ if (!params.Code.ImageConfig.ImageUri) {
902880
+ throw new error_1.CloudBaseError('镜像部署需要配置 imageConfig.imageUri');
902881
+ }
902603
902882
  try {
902604
902883
  // 等待函数状态正常
902605
902884
  await this.waitFunctionActive(funcName, codeSecret);
902606
- return await this.tcbService.request('UpdateFunctionCode', params);
902885
+ return await this.scfService.request('UpdateFunctionCode', params);
902607
902886
  }
902608
902887
  catch (e) {
902609
902888
  throw new error_1.CloudBaseError(`[${funcName}] 函数代码更新失败:${e.message}`, {
@@ -902616,9 +902895,9 @@ class FunctionService {
902616
902895
  let installDependency;
902617
902896
  // Node 函数默认安装依赖
902618
902897
  installDependency = isNodeFunction(func.runtime) ? 'TRUE' : 'FALSE';
902619
- // 是否安装依赖,选项可以覆盖
902620
- if (typeof func.installDependency !== 'undefined') {
902621
- installDependency = func.installDependency ? 'TRUE' : 'FALSE';
902898
+ // 是否安装依赖,选项可以覆盖(支持 boolean | string)
902899
+ if (func.installDependency !== undefined) {
902900
+ installDependency = toBooleanString(func.installDependency);
902622
902901
  }
902623
902902
  const codeParams = await this.getCodeParams({
902624
902903
  func,
@@ -902629,7 +902908,7 @@ class FunctionService {
902629
902908
  }, installDependency);
902630
902909
  const params = {
902631
902910
  FunctionName: funcName,
902632
- EnvId: env,
902911
+ Namespace: namespace,
902633
902912
  Handler: func.handler || 'index.main',
902634
902913
  InstallDependency: installDependency,
902635
902914
  Code: codeParams
@@ -902641,7 +902920,7 @@ class FunctionService {
902641
902920
  // 等待函数状态正常
902642
902921
  await this.waitFunctionActive(funcName, codeSecret);
902643
902922
  // 更新云函数代码
902644
- const res = await this.tcbService.request('UpdateFunctionCode', params);
902923
+ const res = await this.scfService.request('UpdateFunctionCode', params);
902645
902924
  if (installDependency && func.isWaitInstall === true) {
902646
902925
  await this.waitFunctionActive(funcName, codeSecret);
902647
902926
  }
@@ -902783,13 +903062,12 @@ class FunctionService {
902783
903062
  async deleteFunctionTrigger(name, triggerName) {
902784
903063
  const { namespace } = this.getFunctionConfig();
902785
903064
  try {
902786
- await this.scfService.request('DeleteTrigger', {
903065
+ return await this.scfService.request('DeleteTrigger', {
902787
903066
  FunctionName: name,
902788
903067
  Namespace: namespace,
902789
903068
  TriggerName: triggerName,
902790
903069
  Type: 'timer'
902791
903070
  });
902792
- (0, utils_1.successLog)(`[${name}] 删除云函数触发器 ${triggerName} 成功!`);
902793
903071
  }
902794
903072
  catch (e) {
902795
903073
  throw new error_1.CloudBaseError(`[${name}] 删除触发器失败:${e.message}`);
@@ -903025,7 +903303,8 @@ class FunctionService {
903025
903303
  if (Status === constant_1.SCF_STATUS.CREATE_FAILED) {
903026
903304
  const errorDetails = (StatusReasons === null || StatusReasons === void 0 ? void 0 : StatusReasons.map(item => `[${item.ErrorCode}] ${item.ErrorMessage}`).join('\n')) || '';
903027
903305
  const errorMsg = `云函数创建失败${StatusDesc ? `\n状态描述: ${StatusDesc}` : ''}${errorDetails ? `\n失败信息: ${errorDetails}` : ''}`;
903028
- throw new error_1.CloudBaseError(errorMsg, { requestId: RequestId });
903306
+ // 注意:这里不传递 RequestId,因为这是 GetFunction RequestId,不是导致失败的 CreateFunction/UpdateFunctionCode 的 RequestId
903307
+ throw new error_1.CloudBaseError(errorMsg);
903029
903308
  }
903030
903309
  // 函数状态正常
903031
903310
  clearInterval(ticker);
@@ -903205,7 +903484,12 @@ class FunctionService {
903205
903484
  // 清理临时文件
903206
903485
  await packer.clean();
903207
903486
  if (err) {
903208
- reject(new error_1.CloudBaseError(`COS 上传失败: ${err.message || err}`));
903487
+ // 保留完整的错误信息(避免原始错误丢失)
903488
+ const errorMessage = err.message || err.error || String(err);
903489
+ const errorCode = err.code || err.statusCode || '';
903490
+ reject(new error_1.CloudBaseError(`COS 上传失败: ${errorMessage}${errorCode ? ` (${errorCode})` : ''}`, {
903491
+ code: errorCode
903492
+ }));
903209
903493
  }
903210
903494
  else {
903211
903495
  resolve(data);
@@ -903258,7 +903542,16 @@ class FunctionService {
903258
903542
  headers
903259
903543
  });
903260
903544
  if (!response.ok) {
903261
- throw new error_1.CloudBaseError(`上传失败: ${response.status} ${response.statusText}`);
903545
+ // 尝试获取响应体中的错误信息
903546
+ let errorDetail = '';
903547
+ try {
903548
+ const responseText = await response.text();
903549
+ errorDetail = responseText ? ` - ${responseText}` : '';
903550
+ }
903551
+ catch (e) {
903552
+ // 忽略响应体解析错误
903553
+ }
903554
+ throw new error_1.CloudBaseError(`上传失败: ${response.status} ${response.statusText}${errorDetail}`);
903262
903555
  }
903263
903556
  // 清理临时文件
903264
903557
  await packer.clean();