@cloudbase/cloudbase-mcp 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/dist/cli.cjs +574 -177
  2. package/dist/index.cjs +574 -177
  3. package/dist/index.js +156 -141
  4. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -101,6 +101,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
101
101
  Object.defineProperty(exports, "__esModule", ({ value: true }));
102
102
  exports.CloudRunService = void 0;
103
103
  exports.codeToZip = codeToZip;
104
+ exports.parseObjectToDiffConfigItem = parseObjectToDiffConfigItem;
104
105
  const archiver_1 = __importDefault(__webpack_require__(99133));
105
106
  const fs_extra_1 = __webpack_require__(21605);
106
107
  const path_1 = __importDefault(__webpack_require__(39902));
@@ -269,7 +270,7 @@ class CloudRunService {
269
270
  /**
270
271
  * 上传部署包
271
272
  */
272
- const zipFile = await codeToZip(targetPath, { installDependency: true });
273
+ const zipFile = await codeToZip(targetPath, { installDependency: (serverConfig === null || serverConfig === void 0 ? void 0 : serverConfig.InstallDependency) !== undefined ? serverConfig.InstallDependency : true });
273
274
  await (0, utils_1.upload)({
274
275
  url: uploadUrl,
275
276
  file: zipFile,
@@ -285,8 +286,14 @@ class CloudRunService {
285
286
  if (await this._checkFunctionExist(serverName)) {
286
287
  // 更新
287
288
  const serverDetail = await this.detail({ serverName });
288
- const _serverConfig = Object.assign(Object.assign(Object.assign({}, ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig) || {})), serverConfig), ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:' ? { Port: 3000 } : {}) // 函数型不能指定端口,需要固定为3000
289
+ const _serverConfig = Object.assign(Object.assign(Object.assign({}, serverConfig), { OpenAccessTypes: ['OA', 'PUBLIC', 'MINIAPP'] }), ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:' ? { Port: 3000 } : {}) // 函数型不能指定端口,需要固定为3000
289
290
  );
291
+ if ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:') {
292
+ deployInfo.BuildPacks = {
293
+ LanguageVersion: '20.18',
294
+ RepoLanguage: 'Node.js'
295
+ };
296
+ }
290
297
  deployInfo.ReleaseType = 'FULL';
291
298
  return this._upsertFunction(false, {
292
299
  name: serverName,
@@ -314,7 +321,13 @@ class CloudRunService {
314
321
  RepoLanguage: 'Node.js'
315
322
  };
316
323
  }
317
- const _serverConfig = Object.assign(Object.assign(Object.assign({ OpenAccessTypes: ['OA', 'PUBLIC'], Cpu: 0, Mem: 0, MinNum: 0, MaxNum: 0, PolicyDetails: [], EnvParams: JSON.stringify({}), InitialDelaySeconds: 0, CustomLogs: '', HasDockerfile: true, CreateTime: '', EnvId: envConfig.EnvId, ServerName: serverName, Port: type === 'container' ? 80 : 3000, Dockerfile: 'Dockerfile', BuildDir: '' }, serverConfig), (type === 'function' ? { Port: 3000 } : {})), { Tag: type === 'container' ? '' : 'function:' });
324
+ const _serverConfig = Object.assign(Object.assign(Object.assign({ OpenAccessTypes: ['OA', 'PUBLIC', 'MINIAPP'],
325
+ // Cpu: 0,
326
+ // Mem: 0,
327
+ MinNum: 0,
328
+ // MaxNum: 0,
329
+ // PolicyDetails: [],
330
+ EnvParams: JSON.stringify({}), InitialDelaySeconds: 0, CustomLogs: '', HasDockerfile: true, CreateTime: '', EnvId: envConfig.EnvId, ServerName: serverName, Port: type === 'container' ? 80 : 3000, Dockerfile: 'Dockerfile', BuildDir: '' }, serverConfig), (type === 'function' ? { Port: 3000 } : {})), { Tag: type === 'container' ? '' : 'function:' });
318
331
  return this._upsertFunction(true, {
319
332
  name: serverName,
320
333
  deployInfo,
@@ -348,11 +361,12 @@ class CloudRunService {
348
361
  _upsertFunction(isNew, data) {
349
362
  const { name, deployInfo, serverConfig } = data;
350
363
  const envConfig = this.environment.lazyEnvironmentConfig;
364
+ const Items = parseObjectToDiffConfigItem(serverConfig);
351
365
  return this.tcbrService.request(isNew ? 'CreateCloudRunServer' : 'UpdateCloudRunServer', {
352
366
  EnvId: envConfig.EnvId,
353
367
  ServerName: name,
354
368
  DeployInfo: deployInfo,
355
- ServerConfig: serverConfig
369
+ Items,
356
370
  });
357
371
  }
358
372
  }
@@ -425,6 +439,63 @@ async function codeToZip(cwd, options) {
425
439
  await archive.finalize();
426
440
  return bufferPromise;
427
441
  }
442
+ /**
443
+ * 提交参数变化映射
444
+ */
445
+ const SUBMIT_DIFF_MAP = {
446
+ Cpu: 'CpuSpecs',
447
+ Mem: 'MemSpecs',
448
+ OpenAccessTypes: 'AccessTypes',
449
+ EnvParams: 'EnvParam',
450
+ CustomLogs: 'LogPath'
451
+ };
452
+ /**
453
+ * 将 object 参数转为 [{key:"Port", IntValue:80}] 的格式,并且剔除空字符串
454
+ */
455
+ function parseObjectToDiffConfigItem(data) {
456
+ const kvs = Object.entries(data);
457
+ const Items = [];
458
+ kvs.forEach(([k, v]) => {
459
+ const Key = SUBMIT_DIFF_MAP[k] || k;
460
+ if ([
461
+ 'CustomLogs',
462
+ 'EnvParams',
463
+ 'CreateTime',
464
+ 'Dockerfile',
465
+ 'BuildDir',
466
+ 'LogType',
467
+ 'LogSetId',
468
+ 'LogTopicId',
469
+ 'LogParseType',
470
+ 'Tag',
471
+ 'InternalAccess',
472
+ 'InternalDomain',
473
+ 'OperationMode',
474
+ 'SessionAffinity'
475
+ ].includes(k)) {
476
+ !!v && Items.push({ Key, Value: v });
477
+ }
478
+ else if (['MinNum', 'MaxNum', 'InitialDelaySeconds', 'Port'].includes(k)) {
479
+ Items.push({ Key, IntValue: v });
480
+ }
481
+ else if (['HasDockerfile'].includes(k)) {
482
+ Items.push({ Key, BoolValue: v });
483
+ }
484
+ else if (['Cpu', 'Mem'].includes(k)) {
485
+ Items.push({ Key, FloatValue: v });
486
+ }
487
+ else if (['OpenAccessTypes', 'EntryPoint', 'Cmd'].includes(k)) {
488
+ Items.push({ Key, ArrayValue: v });
489
+ }
490
+ else if (['PolicyDetails'].includes(k)) {
491
+ Items.push({ Key, PolicyDetails: v });
492
+ }
493
+ else if (['TimerScale'].includes(k)) {
494
+ Items.push({ Key, TimerScale: v });
495
+ }
496
+ });
497
+ return Items;
498
+ }
428
499
 
429
500
 
430
501
  /***/ }),
@@ -23553,7 +23624,7 @@ async function getCloudBaseManager(options = {}) {
23553
23624
  secretKey,
23554
23625
  envId: finalEnvId || loginEnvId,
23555
23626
  token,
23556
- proxy: process.env.http_proxy
23627
+ proxy: process.env.http_proxy,
23557
23628
  });
23558
23629
  return manager;
23559
23630
  }
@@ -23570,13 +23641,8 @@ async function getCloudBaseManager(options = {}) {
23570
23641
  function createCloudBaseManagerWithOptions(cloudBaseOptions) {
23571
23642
  (0, logger_js_1.debug)('使用传入的 CloudBase 配置创建 manager:', cloudBaseOptions);
23572
23643
  const manager = new manager_node_1.default({
23573
- secretId: cloudBaseOptions.secretId,
23574
- secretKey: cloudBaseOptions.secretKey,
23575
- envId: cloudBaseOptions.envId,
23576
- token: cloudBaseOptions.token,
23644
+ ...cloudBaseOptions,
23577
23645
  proxy: cloudBaseOptions.proxy || process.env.http_proxy,
23578
- region: cloudBaseOptions.region,
23579
- envType: cloudBaseOptions.envType
23580
23646
  });
23581
23647
  return manager;
23582
23648
  }
@@ -48549,7 +48615,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
48549
48615
  exports.cloudBaseRequest = cloudBaseRequest;
48550
48616
  const auth_1 = __webpack_require__(23506);
48551
48617
  const http_request_1 = __webpack_require__(72088);
48552
- const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou'];
48618
+ const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou', 'ap-singapore'];
48553
48619
  async function cloudBaseRequest(options) {
48554
48620
  // const url = 'https://tcb-admin.tencentcloudapi.com/admin'
48555
48621
  const { config, params = {}, method = 'POST', headers = {} } = options;
@@ -48563,11 +48629,11 @@ async function cloudBaseRequest(options) {
48563
48629
  let internalRegionEndpoint = '';
48564
48630
  if (finalRegion) {
48565
48631
  if (SUPPORT_REGIONS.includes(finalRegion)) {
48566
- internetRegionEndpoint = `${finalRegion}.tcb-api.tencentcloudapi.com`;
48567
- internalRegionEndpoint = `internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48632
+ internetRegionEndpoint = `${envId}.${finalRegion}.tcb-api.tencentcloudapi.com`;
48633
+ internalRegionEndpoint = `${envId}.internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48568
48634
  }
48569
48635
  else {
48570
- console.warn('当前仅支持上海,广州地域,其他地域默认解析到固定域名(上海地域)');
48636
+ console.warn('当前仅支持上海,广州,新加坡地域,其他地域默认解析到固定域名(上海地域)');
48571
48637
  internetRegionEndpoint = `tcb-api.tencentcloudapi.com`;
48572
48638
  internalRegionEndpoint = `internal.tcb-api.tencentcloudapi.com`;
48573
48639
  }
@@ -90160,19 +90226,20 @@ class EnvService {
90160
90226
  });
90161
90227
  }
90162
90228
  getCos() {
90229
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
90163
90230
  const { secretId, secretKey, token } = this.environment.getAuthConfig();
90164
90231
  const cosConfig = {
90165
90232
  SecretId: secretId,
90166
90233
  SecretKey: secretKey,
90167
90234
  SecurityToken: token,
90168
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90235
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90169
90236
  };
90170
90237
  if (constant_1.COS_SDK_PROTOCOL) {
90171
90238
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
90172
90239
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
90173
90240
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
90174
90241
  }
90175
- if (constant_1.USE_INTERNAL_ENDPOINT) {
90242
+ if (internalEndpoint) {
90176
90243
  cosConfig.Protocol = 'http:';
90177
90244
  }
90178
90245
  return new cos_nodejs_sdk_v5_1.default(cosConfig);
@@ -134866,7 +134933,7 @@ class TelemetryReporter {
134866
134933
  const nodeVersion = process.version; // Node.js版本
134867
134934
  const arch = os_1.default.arch(); // 系统架构
134868
134935
  // 从构建时注入的版本号获取MCP版本信息
134869
- const mcpVersion = process.env.npm_package_version || "2.1.0" || 0;
134936
+ const mcpVersion = process.env.npm_package_version || "2.2.0" || 0;
134870
134937
  return {
134871
134938
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
134872
134939
  deviceId: this.deviceId,
@@ -179464,6 +179531,7 @@ exports.sleep = sleep;
179464
179531
  exports.upperCaseStringFisrt = upperCaseStringFisrt;
179465
179532
  exports.upperCaseObjKey = upperCaseObjKey;
179466
179533
  exports.fetchTemplates = fetchTemplates;
179534
+ exports.successLog = successLog;
179467
179535
  const archiver_1 = __importDefault(__webpack_require__(99133));
179468
179536
  const crypto_1 = __importDefault(__webpack_require__(55511));
179469
179537
  const fs_extra_1 = __importDefault(__webpack_require__(21605));
@@ -179742,6 +179810,10 @@ const getCompleteTimeRange = (timeRange) => {
179742
179810
  };
179743
179811
  };
179744
179812
  exports.getCompleteTimeRange = getCompleteTimeRange;
179813
+ function successLog(msg) {
179814
+ // 空格,兼容中文字符编码长度问题
179815
+ console.log(`${msg}`);
179816
+ }
179745
179817
 
179746
179818
 
179747
179819
  /***/ }),
@@ -191070,20 +191142,25 @@ function callSuccessCallback(callback, result) {
191070
191142
  /***/ }),
191071
191143
 
191072
191144
  /***/ 65607:
191073
- /***/ ((__unused_webpack_module, exports) => {
191145
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
191074
191146
 
191075
191147
  "use strict";
191076
191148
 
191077
191149
  Object.defineProperty(exports, "__esModule", ({ value: true }));
191078
191150
  exports.CloudBaseContext = void 0;
191151
+ const constant_1 = __webpack_require__(40762);
191079
191152
  class CloudBaseContext {
191080
- constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '' }) {
191153
+ constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined }) {
191081
191154
  this.secretId = secretId;
191082
191155
  this.secretKey = secretKey;
191083
191156
  this.token = token;
191084
191157
  this.proxy = proxy;
191085
191158
  this.region = region;
191086
191159
  this.envType = envType;
191160
+ this.useInternalEndpoint = useInternalEndpoint;
191161
+ }
191162
+ isInternalEndpoint() {
191163
+ return this.useInternalEndpoint !== undefined ? this.useInternalEndpoint : constant_1.USE_INTERNAL_ENDPOINT;
191087
191164
  }
191088
191165
  }
191089
191166
  exports.CloudBaseContext = CloudBaseContext;
@@ -200610,7 +200687,7 @@ ${envIdSection}
200610
200687
  ## 环境信息
200611
200688
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
200612
200689
  - Node.js版本: ${process.version}
200613
- - MCP 版本:${process.env.npm_package_version || "2.1.0" || 0}
200690
+ - MCP 版本:${process.env.npm_package_version || "2.2.0" || 0}
200614
200691
  - 系统架构: ${os_1.default.arch()}
200615
200692
  - 时间: ${new Date().toISOString()}
200616
200693
  - 请求ID: ${requestId}
@@ -203502,6 +203579,7 @@ class StorageService {
203502
203579
  * 获取 COS 配置
203503
203580
  */
203504
203581
  getCos(parallel = 20) {
203582
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
203505
203583
  const { secretId, secretKey, token, proxy } = this.environment.getAuthConfig();
203506
203584
  const cosProxy = process.env.TCB_COS_PROXY;
203507
203585
  const cosConfig = {
@@ -203510,14 +203588,14 @@ class StorageService {
203510
203588
  SecretKey: secretKey,
203511
203589
  Proxy: cosProxy || proxy,
203512
203590
  SecurityToken: token,
203513
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203591
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203514
203592
  };
203515
203593
  if (constant_1.COS_SDK_PROTOCOL) {
203516
203594
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
203517
203595
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
203518
203596
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
203519
203597
  }
203520
- if (constant_1.USE_INTERNAL_ENDPOINT) {
203598
+ if (internalEndpoint) {
203521
203599
  cosConfig.Protocol = 'http:';
203522
203600
  }
203523
203601
  // COSSDK 默认开启 KeepAlive,这里提供关闭的方式
@@ -214909,26 +214987,26 @@ const path = __importStar(__webpack_require__(39902));
214909
214987
  const zod_1 = __webpack_require__(21614);
214910
214988
  // CloudBase 模板配置
214911
214989
  const TEMPLATES = {
214912
- "react": {
214990
+ react: {
214913
214991
  description: "React + CloudBase 全栈应用模板",
214914
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip"
214992
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip",
214915
214993
  },
214916
- "vue": {
214994
+ vue: {
214917
214995
  description: "Vue + CloudBase 全栈应用模板",
214918
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip"
214996
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip",
214919
214997
  },
214920
- "miniprogram": {
214998
+ miniprogram: {
214921
214999
  description: "微信小程序 + 云开发模板",
214922
- url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip"
215000
+ url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip",
214923
215001
  },
214924
- "uniapp": {
215002
+ uniapp: {
214925
215003
  description: "UniApp + CloudBase 跨端应用模板",
214926
- url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip"
215004
+ url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip",
214927
215005
  },
214928
- "rules": {
215006
+ rules: {
214929
215007
  description: "AI编辑器配置模板(包含所有主流编辑器配置)",
214930
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip"
214931
- }
215008
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip",
215009
+ },
214932
215010
  };
214933
215011
  // IDE类型枚举
214934
215012
  const IDE_TYPES = [
@@ -214948,22 +215026,13 @@ const IDE_TYPES = [
214948
215026
  "roocode", // RooCode AI编辑器
214949
215027
  "tongyi-lingma", // 通义灵码
214950
215028
  "trae", // Trae AI编辑器
214951
- "vscode" // Visual Studio Code
215029
+ "vscode", // Visual Studio Code
214952
215030
  ];
214953
215031
  // IDE到文件的映射关系
214954
215032
  const IDE_FILE_MAPPINGS = {
214955
- "cursor": [
214956
- ".cursor/rules/cloudbase-rules.mdc",
214957
- ".cursor/mcp.json"
214958
- ],
214959
- "windsurf": [
214960
- ".windsurf/rules/cloudbase-rules.md"
214961
- ],
214962
- "codebuddy": [
214963
- ".rules/cloudbase-rules.md",
214964
- "CODEBUDDY.md",
214965
- ".mcp.json"
214966
- ],
215033
+ cursor: [".cursor/rules/cloudbase-rules.mdc", ".cursor/mcp.json"],
215034
+ windsurf: [".windsurf/rules/cloudbase-rules.md"],
215035
+ codebuddy: [".rules/cloudbase-rules.md", "CODEBUDDY.md", ".mcp.json"],
214967
215036
  "claude-code": [
214968
215037
  "CLAUDE.md",
214969
215038
  ".mcp.json",
@@ -214972,49 +215041,22 @@ const IDE_FILE_MAPPINGS = {
214972
215041
  ".claude/commands/spec.md",
214973
215042
  ".claude/commands/no_spec.md",
214974
215043
  ],
214975
- "cline": [
214976
- ".clinerules/cloudbase-rules.mdc"
214977
- ],
214978
- "gemini-cli": [
214979
- ".gemini/GEMINI.md",
214980
- ".gemini/settings.json"
214981
- ],
214982
- "opencode": [
214983
- ".opencode.json"
214984
- ],
214985
- "qwen-code": [
214986
- ".qwen/QWEN.md",
214987
- ".qwen/settings.json"
214988
- ],
215044
+ cline: [".clinerules/cloudbase-rules.mdc"],
215045
+ "gemini-cli": [".gemini/GEMINI.md", ".gemini/settings.json"],
215046
+ opencode: [".opencode.json"],
215047
+ "qwen-code": [".qwen/QWEN.md", ".qwen/settings.json"],
214989
215048
  "baidu-comate": [
214990
215049
  ".comate/rules/cloudbase-rules.mdr",
214991
215050
  ".comate/rules/cloudbaase-rules.mdr",
214992
- ".comate/mcp.json"
214993
- ],
214994
- "openai-codex-cli": [
214995
- ".codex/config.toml",
214996
- "AGENTS.md",
214997
- ],
214998
- "augment-code": [
214999
- ".augment-guidelines"
215051
+ ".comate/mcp.json",
215000
215052
  ],
215001
- "github-copilot": [
215002
- ".github/copilot-instructions.md"
215003
- ],
215004
- "roocode": [
215005
- ".roo/rules/cloudbaase-rules.md",
215006
- ".roo/mcp.json"
215007
- ],
215008
- "tongyi-lingma": [
215009
- ".lingma/rules/cloudbaase-rules.md"
215010
- ],
215011
- "trae": [
215012
- ".trae/rules/cloudbase-rules.md"
215013
- ],
215014
- "vscode": [
215015
- ".vscode/mcp.json",
215016
- ".vscode/settings.json"
215017
- ]
215053
+ "openai-codex-cli": [".codex/config.toml", "AGENTS.md"],
215054
+ "augment-code": [".augment-guidelines"],
215055
+ "github-copilot": [".github/copilot-instructions.md"],
215056
+ roocode: [".roo/rules/cloudbaase-rules.md", ".roo/mcp.json"],
215057
+ "tongyi-lingma": [".lingma/rules/cloudbaase-rules.md"],
215058
+ trae: [".trae/rules/cloudbase-rules.md"],
215059
+ vscode: [".vscode/mcp.json", ".vscode/settings.json"],
215018
215060
  };
215019
215061
  // 所有IDE配置文件的完整列表 - 通过IDE_FILE_MAPPINGS计算得出
215020
215062
  const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()));
@@ -215022,51 +215064,87 @@ const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()
215022
215064
  IDE_FILE_MAPPINGS["all"] = ALL_IDE_FILES;
215023
215065
  // IDE描述映射
215024
215066
  const IDE_DESCRIPTIONS = {
215025
- "all": "所有IDE配置",
215026
- "cursor": "Cursor AI编辑器",
215027
- "windsurf": "WindSurf AI编辑器",
215028
- "codebuddy": "CodeBuddy AI编辑器",
215067
+ all: "所有IDE配置",
215068
+ cursor: "Cursor AI编辑器",
215069
+ windsurf: "WindSurf AI编辑器",
215070
+ codebuddy: "CodeBuddy AI编辑器",
215029
215071
  "claude-code": "Claude Code AI编辑器",
215030
- "cline": "Cline AI编辑器",
215072
+ cline: "Cline AI编辑器",
215031
215073
  "gemini-cli": "Gemini CLI",
215032
- "opencode": "OpenCode AI编辑器",
215074
+ opencode: "OpenCode AI编辑器",
215033
215075
  "qwen-code": "通义灵码",
215034
215076
  "baidu-comate": "百度Comate",
215035
215077
  "openai-codex-cli": "OpenAI Codex CLI",
215036
215078
  "augment-code": "Augment Code",
215037
215079
  "github-copilot": "GitHub Copilot",
215038
- "roocode": "RooCode AI编辑器",
215080
+ roocode: "RooCode AI编辑器",
215039
215081
  "tongyi-lingma": "通义灵码",
215040
- "trae": "Trae AI编辑器",
215041
- "vscode": "Visual Studio Code"
215042
- };
215082
+ trae: "Trae AI编辑器",
215083
+ vscode: "Visual Studio Code",
215084
+ };
215085
+ // INTEGRATION_IDE 环境变量值到 IDE 类型的映射
215086
+ const INTEGRATION_IDE_MAPPING = {
215087
+ Cursor: "cursor",
215088
+ WindSurf: "windsurf",
215089
+ CodeBuddy: "codebuddy",
215090
+ CodeBuddyManual: "codebuddy",
215091
+ CodeBuddyCode: "codebuddy",
215092
+ "Claude Code": "claude-code",
215093
+ CLINE: "cline",
215094
+ "Gemini CLI": "gemini-cli",
215095
+ OpenCode: "opencode",
215096
+ "Qwen Code": "qwen-code",
215097
+ "Baidu Comate": "baidu-comate",
215098
+ "OpenAI Codex CLI": "openai-codex-cli",
215099
+ "Augment Code": "augment-code",
215100
+ "GitHub Copilot": "github-copilot",
215101
+ RooCode: "roocode",
215102
+ "Tongyi Lingma": "tongyi-lingma",
215103
+ Trae: "trae",
215104
+ VSCode: "vscode",
215105
+ };
215106
+ // 根据 INTEGRATION_IDE 环境变量获取默认 IDE 类型
215107
+ function getDefaultIDEFromEnv() {
215108
+ const integrationIDE = process.env.INTEGRATION_IDE;
215109
+ if (integrationIDE) {
215110
+ const mappedIDE = INTEGRATION_IDE_MAPPING[integrationIDE];
215111
+ if (mappedIDE) {
215112
+ return mappedIDE;
215113
+ }
215114
+ }
215115
+ return "all";
215116
+ }
215043
215117
  // 下载文件到临时目录
215044
215118
  async function downloadFile(url, filePath) {
215045
215119
  return new Promise((resolve, reject) => {
215046
- const client = url.startsWith('https:') ? https : http;
215047
- client.get(url, (res) => {
215120
+ const client = url.startsWith("https:") ? https : http;
215121
+ client
215122
+ .get(url, (res) => {
215048
215123
  if (res.statusCode === 200) {
215049
215124
  const file = fs.createWriteStream(filePath);
215050
215125
  res.pipe(file);
215051
- file.on('finish', () => {
215126
+ file.on("finish", () => {
215052
215127
  file.close();
215053
215128
  resolve();
215054
215129
  });
215055
- file.on('error', reject);
215130
+ file.on("error", reject);
215056
215131
  }
215057
215132
  else if (res.statusCode === 302 || res.statusCode === 301) {
215058
215133
  // 处理重定向
215059
215134
  if (res.headers.location) {
215060
- downloadFile(res.headers.location, filePath).then(resolve).catch(reject);
215135
+ downloadFile(res.headers.location, filePath)
215136
+ .then(resolve)
215137
+ .catch(reject);
215061
215138
  }
215062
215139
  else {
215063
- reject(new Error('重定向但没有location header'));
215140
+ reject(new Error("重定向但没有location header"));
215064
215141
  }
215065
215142
  }
215066
215143
  else {
215067
215144
  reject(new Error(`下载失败,状态码: ${res.statusCode}`));
215068
215145
  }
215069
- }).on('error', reject);
215146
+ })
215147
+ .on("error", reject);
215070
215148
  });
215071
215149
  }
215072
215150
  // 解压ZIP文件
@@ -215079,7 +215157,7 @@ async function extractZip(zipPath, extractPath) {
215079
215157
  zip.extractAllTo(extractPath, true);
215080
215158
  }
215081
215159
  catch (error) {
215082
- throw new Error(`解压失败: ${error instanceof Error ? error.message : '未知错误'}`);
215160
+ throw new Error(`解压失败: ${error instanceof Error ? error.message : "未知错误"}`);
215083
215161
  }
215084
215162
  }
215085
215163
  // 获取目录下所有文件的相对路径列表
@@ -215103,7 +215181,7 @@ async function copyFileIfNotExists(src, dest) {
215103
215181
  try {
215104
215182
  // 检查目标文件是否存在
215105
215183
  if (fs.existsSync(dest)) {
215106
- return { copied: false, reason: '文件已存在' };
215184
+ return { copied: false, reason: "文件已存在" };
215107
215185
  }
215108
215186
  // 创建目标目录
215109
215187
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -215112,14 +215190,17 @@ async function copyFileIfNotExists(src, dest) {
215112
215190
  return { copied: true };
215113
215191
  }
215114
215192
  catch (error) {
215115
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215193
+ return {
215194
+ copied: false,
215195
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215196
+ };
215116
215197
  }
215117
215198
  }
215118
215199
  // 复制文件,支持覆盖模式
215119
215200
  // 判断是否应该跳过 README.md 文件
215120
215201
  function shouldSkipReadme(template, destPath, overwrite) {
215121
- const isReadme = path.basename(destPath).toLowerCase() === 'readme.md';
215122
- const isRulesTemplate = template === 'rules';
215202
+ const isReadme = path.basename(destPath).toLowerCase() === "readme.md";
215203
+ const isRulesTemplate = template === "rules";
215123
215204
  const exists = fs.existsSync(destPath);
215124
215205
  return isReadme && isRulesTemplate && exists && !overwrite;
215125
215206
  }
@@ -215128,11 +215209,15 @@ async function copyFile(src, dest, overwrite = false, template) {
215128
215209
  const destExists = fs.existsSync(dest);
215129
215210
  // 检查是否需要跳过 README.md 文件(仅对 rules 模板)
215130
215211
  if (template && shouldSkipReadme(template, dest, overwrite)) {
215131
- return { copied: false, reason: 'README.md 文件已存在,已保护', action: 'protected' };
215212
+ return {
215213
+ copied: false,
215214
+ reason: "README.md 文件已存在,已保护",
215215
+ action: "protected",
215216
+ };
215132
215217
  }
215133
215218
  // 如果目标文件存在且不允许覆盖
215134
215219
  if (destExists && !overwrite) {
215135
- return { copied: false, reason: '文件已存在', action: 'skipped' };
215220
+ return { copied: false, reason: "文件已存在", action: "skipped" };
215136
215221
  }
215137
215222
  // 创建目标目录
215138
215223
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -215140,11 +215225,14 @@ async function copyFile(src, dest, overwrite = false, template) {
215140
215225
  await fsPromises.copyFile(src, dest);
215141
215226
  return {
215142
215227
  copied: true,
215143
- action: destExists ? 'overwritten' : 'created'
215228
+ action: destExists ? "overwritten" : "created",
215144
215229
  };
215145
215230
  }
215146
215231
  catch (error) {
215147
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215232
+ return {
215233
+ copied: false,
215234
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215235
+ };
215148
215236
  }
215149
215237
  }
215150
215238
  // IDE验证函数
@@ -215152,13 +215240,13 @@ function validateIDE(ide) {
215152
215240
  if (ide === "all") {
215153
215241
  return { valid: true };
215154
215242
  }
215155
- const supportedIDEs = IDE_TYPES.filter(type => type !== "all");
215243
+ const supportedIDEs = IDE_TYPES.filter((type) => type !== "all");
215156
215244
  const isValid = supportedIDEs.includes(ide);
215157
215245
  if (!isValid) {
215158
215246
  return {
215159
215247
  valid: false,
215160
215248
  error: `不支持的IDE类型: ${ide}`,
215161
- supportedIDEs: supportedIDEs
215249
+ supportedIDEs: supportedIDEs,
215162
215250
  };
215163
215251
  }
215164
215252
  return { valid: true };
@@ -215173,9 +215261,9 @@ function filterFilesByIDE(files, ide) {
215173
215261
  return files; // 如果找不到映射,返回所有文件
215174
215262
  }
215175
215263
  // 计算需要排除的IDE文件(除了当前IDE需要的文件)
215176
- const filesToExclude = ALL_IDE_FILES.filter(file => !ideFiles.includes(file));
215264
+ const filesToExclude = ALL_IDE_FILES.filter((file) => !ideFiles.includes(file));
215177
215265
  // 排除不需要的IDE配置文件,保留其他所有文件
215178
- return files.filter(file => !filesToExclude.includes(file));
215266
+ return files.filter((file) => !filesToExclude.includes(file));
215179
215267
  }
215180
215268
  // 创建过滤后的目录结构
215181
215269
  async function createFilteredDirectory(extractDir, filteredFiles, ide) {
@@ -215183,7 +215271,7 @@ async function createFilteredDirectory(extractDir, filteredFiles, ide) {
215183
215271
  return extractDir; // 如果选择所有IDE,直接返回原目录
215184
215272
  }
215185
215273
  // 创建新的过滤后目录
215186
- const filteredDir = path.join(path.dirname(extractDir), 'filtered');
215274
+ const filteredDir = path.join(path.dirname(extractDir), "filtered");
215187
215275
  await fsPromises.mkdir(filteredDir, { recursive: true });
215188
215276
  // 只复制过滤后的文件到新目录
215189
215277
  for (const relativePath of filteredFiles) {
@@ -215202,32 +215290,42 @@ function registerSetupTools(server) {
215202
215290
  title: "下载项目模板",
215203
215291
  description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
215204
215292
 
215205
- **CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置(默认)\n- cursor: Cursor AI编辑器\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- vscode: Visual Studio Code\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.1.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215293
+ **CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置(默认)\n- cursor: Cursor AI编辑器\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- vscode: Visual Studio Code\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.2.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215206
215294
  inputSchema: {
215207
- template: zod_1.z.enum(["react", "vue", "miniprogram", "uniapp", "rules"]).describe("要下载的模板类型"),
215208
- ide: zod_1.z.enum(IDE_TYPES).optional().default("all").describe("指定要下载的IDE类型,默认为all(下载所有IDE配置)"),
215209
- overwrite: zod_1.z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)")
215295
+ template: zod_1.z
215296
+ .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
215297
+ .describe("要下载的模板类型"),
215298
+ ide: zod_1.z
215299
+ .enum(IDE_TYPES)
215300
+ .optional()
215301
+ .describe("指定要下载的IDE类型。如果未指定,会根据 INTEGRATION_IDE 环境变量自动选择对应的IDE配置;如果环境变量也未设置,则默认下载所有IDE配置"),
215302
+ overwrite: zod_1.z
215303
+ .boolean()
215304
+ .optional()
215305
+ .describe("是否覆盖已存在的文件,默认为false(不覆盖)"),
215210
215306
  },
215211
215307
  annotations: {
215212
215308
  readOnlyHint: false,
215213
215309
  destructiveHint: false,
215214
215310
  idempotentHint: false,
215215
215311
  openWorldHint: true,
215216
- category: "setup"
215217
- }
215218
- }, async ({ template, ide = "all", overwrite = false }) => {
215312
+ category: "setup",
215313
+ },
215314
+ }, async ({ template, ide, overwrite = false, }) => {
215219
215315
  try {
215316
+ // 如果没有传入 ide 参数,根据 INTEGRATION_IDE 环境变量获取默认值
215317
+ const resolvedIDE = ide ?? getDefaultIDEFromEnv();
215220
215318
  // 验证IDE类型
215221
- const ideValidation = validateIDE(ide);
215319
+ const ideValidation = validateIDE(resolvedIDE);
215222
215320
  if (!ideValidation.valid) {
215223
- const supportedIDEs = ideValidation.supportedIDEs?.join(', ') || '';
215321
+ const supportedIDEs = ideValidation.supportedIDEs?.join(", ") || "";
215224
215322
  return {
215225
215323
  content: [
215226
215324
  {
215227
215325
  type: "text",
215228
- text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`
215229
- }
215230
- ]
215326
+ text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`,
215327
+ },
215328
+ ],
215231
215329
  };
215232
215330
  }
215233
215331
  const templateConfig = TEMPLATES[template];
@@ -215236,23 +215334,23 @@ function registerSetupTools(server) {
215236
215334
  content: [
215237
215335
  {
215238
215336
  type: "text",
215239
- text: `❌ 不支持的模板类型: ${template}`
215240
- }
215241
- ]
215337
+ text: `❌ 不支持的模板类型: ${template}`,
215338
+ },
215339
+ ],
215242
215340
  };
215243
215341
  }
215244
215342
  // 创建临时目录
215245
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloudbase-template-'));
215246
- const zipPath = path.join(tempDir, 'template.zip');
215247
- const extractDir = path.join(tempDir, 'extracted');
215343
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cloudbase-template-"));
215344
+ const zipPath = path.join(tempDir, "template.zip");
215345
+ const extractDir = path.join(tempDir, "extracted");
215248
215346
  // 下载和解压
215249
215347
  await downloadFile(templateConfig.url, zipPath);
215250
215348
  await extractZip(zipPath, extractDir);
215251
215349
  const extractedFiles = await getAllFiles(extractDir);
215252
215350
  // 根据IDE类型过滤文件
215253
- const filteredFiles = filterFilesByIDE(extractedFiles, ide);
215351
+ const filteredFiles = filterFilesByIDE(extractedFiles, resolvedIDE);
215254
215352
  // 创建过滤后的目录结构(当选择特定IDE时)
215255
- const workingDir = await createFilteredDirectory(extractDir, filteredFiles, ide);
215353
+ const workingDir = await createFilteredDirectory(extractDir, filteredFiles, resolvedIDE);
215256
215354
  // 检查是否需要复制到项目目录
215257
215355
  const workspaceFolder = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
215258
215356
  let finalFiles = [];
@@ -215267,7 +215365,7 @@ function registerSetupTools(server) {
215267
215365
  const destPath = path.join(workspaceFolder, relativePath);
215268
215366
  const copyResult = await copyFile(srcPath, destPath, overwrite, template);
215269
215367
  if (copyResult.copied) {
215270
- if (copyResult.action === 'overwritten') {
215368
+ if (copyResult.action === "overwritten") {
215271
215369
  overwrittenCount++;
215272
215370
  }
215273
215371
  else {
@@ -215276,7 +215374,7 @@ function registerSetupTools(server) {
215276
215374
  finalFiles.push(destPath);
215277
215375
  }
215278
215376
  else {
215279
- if (copyResult.action === 'protected') {
215377
+ if (copyResult.action === "protected") {
215280
215378
  protectedCount++;
215281
215379
  }
215282
215380
  else {
@@ -215286,11 +215384,11 @@ function registerSetupTools(server) {
215286
215384
  }
215287
215385
  }
215288
215386
  // 添加IDE过滤信息
215289
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215387
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215290
215388
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 同步完成`);
215291
215389
  results.push(`📁 临时目录: ${workingDir}`);
215292
215390
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215293
- if (ide !== "all") {
215391
+ if (resolvedIDE !== "all") {
215294
215392
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215295
215393
  }
215296
215394
  const stats = [];
@@ -215303,36 +215401,36 @@ function registerSetupTools(server) {
215303
215401
  if (skippedCount > 0)
215304
215402
  stats.push(`跳过 ${skippedCount} 个已存在文件`);
215305
215403
  if (stats.length > 0) {
215306
- results.push(`📊 ${stats.join('')}`);
215404
+ results.push(`📊 ${stats.join("")}`);
215307
215405
  }
215308
215406
  if (overwrite || overwrittenCount > 0 || skippedCount > 0) {
215309
- results.push(`🔄 覆盖模式: ${overwrite ? '启用' : '禁用'}`);
215407
+ results.push(`🔄 覆盖模式: ${overwrite ? "启用" : "禁用"}`);
215310
215408
  }
215311
215409
  }
215312
215410
  else {
215313
- finalFiles = filteredFiles.map(relativePath => path.join(workingDir, relativePath));
215314
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215411
+ finalFiles = filteredFiles.map((relativePath) => path.join(workingDir, relativePath));
215412
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215315
215413
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 下载完成`);
215316
215414
  results.push(`📁 保存在临时目录: ${workingDir}`);
215317
215415
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215318
- if (ide !== "all") {
215416
+ if (resolvedIDE !== "all") {
215319
215417
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215320
215418
  }
215321
- results.push('💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。');
215419
+ results.push("💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。");
215322
215420
  }
215323
215421
  // 文件路径列表
215324
- results.push('');
215325
- results.push('📋 文件列表:');
215326
- finalFiles.forEach(filePath => {
215422
+ results.push("");
215423
+ results.push("📋 文件列表:");
215424
+ finalFiles.forEach((filePath) => {
215327
215425
  results.push(`${filePath}`);
215328
215426
  });
215329
215427
  return {
215330
215428
  content: [
215331
215429
  {
215332
215430
  type: "text",
215333
- text: results.join('\n')
215334
- }
215335
- ]
215431
+ text: results.join("\n"),
215432
+ },
215433
+ ],
215336
215434
  };
215337
215435
  }
215338
215436
  catch (error) {
@@ -215340,9 +215438,9 @@ function registerSetupTools(server) {
215340
215438
  content: [
215341
215439
  {
215342
215440
  type: "text",
215343
- text: `❌ 下载模板失败: ${error instanceof Error ? error.message : '未知错误'}`
215344
- }
215345
- ]
215441
+ text: `❌ 下载模板失败: ${error instanceof Error ? error.message : "未知错误"}`,
215442
+ },
215443
+ ],
215346
215444
  };
215347
215445
  }
215348
215446
  });
@@ -226294,6 +226392,7 @@ class CloudService {
226294
226392
  this.cloudBaseContext = context;
226295
226393
  }
226296
226394
  get baseUrl() {
226395
+ const internalEndpoint = this.cloudBaseContext.isInternalEndpoint();
226297
226396
  const tcb = process.env.TCB_BASE_URL || 'https://tcb.tencentcloudapi.com';
226298
226397
  const urlMap = {
226299
226398
  tcb,
@@ -226307,7 +226406,7 @@ class CloudService {
226307
226406
  const intranetUrlMap = Object.keys(urlMap).map((service) => ({
226308
226407
  [service]: `https://${service}.internal.tencentcloudapi.com`,
226309
226408
  })).reduce((acc, cur) => (Object.assign(Object.assign({}, acc), cur)), {});
226310
- if (constant_1.USE_INTERNAL_ENDPOINT) {
226409
+ if (internalEndpoint) {
226311
226410
  return intranetUrlMap[this.service];
226312
226411
  }
226313
226412
  if (urlMap[this.service]) {
@@ -269940,7 +270039,7 @@ class CloudBase {
269940
270039
  }
269941
270040
  constructor(config = {}) {
269942
270041
  this.cloudBaseConfig = {};
269943
- let { secretId, secretKey, token, envId, proxy, region, envType } = config;
270042
+ let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint } = config;
269944
270043
  // config 中传入的 secretId secretkey 必须同时存在
269945
270044
  if ((secretId && !secretKey) || (!secretId && secretKey)) {
269946
270045
  throw new Error('secretId and secretKey must be a pair');
@@ -269952,7 +270051,8 @@ class CloudBase {
269952
270051
  envId,
269953
270052
  envType,
269954
270053
  proxy,
269955
- region
270054
+ region,
270055
+ useInternalEndpoint
269956
270056
  };
269957
270057
  // 初始化 context
269958
270058
  this.context = new context_1.CloudBaseContext(this.cloudBaseConfig);
@@ -270007,6 +270107,9 @@ class CloudBase {
270007
270107
  getManagerConfig() {
270008
270108
  return this.cloudBaseConfig;
270009
270109
  }
270110
+ get isInternalEndpoint() {
270111
+ return this.context.isInternalEndpoint();
270112
+ }
270010
270113
  }
270011
270114
  module.exports = CloudBase;
270012
270115
 
@@ -272085,6 +272188,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
272085
272188
  exports.FunctionService = void 0;
272086
272189
  const fs_1 = __importDefault(__webpack_require__(29021));
272087
272190
  const path_1 = __importDefault(__webpack_require__(39902));
272191
+ const lodash_1 = __importDefault(__webpack_require__(2543));
272088
272192
  const packer_1 = __webpack_require__(5147);
272089
272193
  const error_1 = __webpack_require__(40430);
272090
272194
  const utils_1 = __webpack_require__(62358);
@@ -272331,20 +272435,96 @@ class FunctionService {
272331
272435
  });
272332
272436
  return data;
272333
272437
  }
272438
+ /**
272439
+ * 列出所有函数
272440
+ * @param {IListFunctionOptions} options
272441
+ * @returns {Promise<Record<string, string>[]>}
272442
+ */
272443
+ async listAllFunctions(options) {
272444
+ const allFunctions = [];
272445
+ let currentOffset = 0;
272446
+ const pageSize = 20;
272447
+ const { envId } = options;
272448
+ while (true) {
272449
+ try {
272450
+ const res = await this.scfService.request('ListFunctions', {
272451
+ Namespace: envId,
272452
+ Limit: pageSize,
272453
+ Offset: currentOffset
272454
+ });
272455
+ const { Functions = [], TotalCount } = res;
272456
+ if (Functions.length === 0) {
272457
+ break;
272458
+ }
272459
+ allFunctions.push(...Functions);
272460
+ // 检查是否已获取所有函数
272461
+ if (allFunctions.length >= TotalCount || Functions.length < pageSize) {
272462
+ break;
272463
+ }
272464
+ currentOffset += pageSize;
272465
+ }
272466
+ catch (error) {
272467
+ throw new error_1.CloudBaseError(`获取函数列表失败: ${error.message}`);
272468
+ }
272469
+ }
272470
+ // 格式化数据
272471
+ const data = [];
272472
+ allFunctions.forEach(func => {
272473
+ const { FunctionId, FunctionName, Runtime, AddTime, ModTime, Status } = func;
272474
+ data.push({
272475
+ FunctionId,
272476
+ FunctionName,
272477
+ Runtime,
272478
+ AddTime,
272479
+ ModTime,
272480
+ Status
272481
+ });
272482
+ });
272483
+ return data;
272484
+ }
272334
272485
  /**
272335
272486
  * 删除云函数
272336
272487
  * @param {string} name 云函数名称
272337
272488
  * @param {string} qualifier 需要删除的版本号,不填默认删除函数下全部版本。
272338
272489
  * @returns {Promise<IResponseInfo>}
272339
272490
  */
272340
- async deleteFunction(name, qualifier) {
272491
+ async deleteFunction({ name }) {
272492
+ var _a;
272341
272493
  const { namespace } = this.getFunctionConfig();
272342
- return this.scfService.request('DeleteFunction', {
272494
+ // 检测是否绑定了 API 网关
272495
+ const accessService = this.environment.getAccessService();
272496
+ const res = await accessService.getAccessList({
272497
+ name
272498
+ });
272499
+ // 删除绑定的 API 网关
272500
+ if (((_a = res === null || res === void 0 ? void 0 : res.APISet) === null || _a === void 0 ? void 0 : _a.length) > 0) {
272501
+ await accessService.deleteAccess({
272502
+ name
272503
+ });
272504
+ }
272505
+ await this.scfService.request('DeleteFunction', {
272343
272506
  FunctionName: name,
272344
- Namespace: namespace,
272345
- Qualifier: qualifier
272507
+ Namespace: namespace
272346
272508
  });
272347
272509
  }
272510
+ /**
272511
+ * 批量删除云函数
272512
+ * @param {Object} options
272513
+ * @param {string[]} options.names 云函数名称列表
272514
+ * @returns {Promise<void>}
272515
+ */
272516
+ async batchDeleteFunctions({ names }) {
272517
+ const promises = names.map(name => (async () => {
272518
+ try {
272519
+ await this.deleteFunction({ name });
272520
+ (0, utils_1.successLog)(`[${name}] 函数删除成功!`);
272521
+ }
272522
+ catch (e) {
272523
+ throw new error_1.CloudBaseError(e.message);
272524
+ }
272525
+ })());
272526
+ await Promise.all(promises);
272527
+ }
272348
272528
  /**
272349
272529
  * 获取云函数详细信息
272350
272530
  * @param {string} name 云函数名称
@@ -272379,13 +272559,35 @@ class FunctionService {
272379
272559
  }
272380
272560
  catch (e) {
272381
272561
  data.VpcConfig = {
272382
- vpc: '',
272383
- subnet: ''
272562
+ vpc: 'VpcId',
272563
+ subnet: 'SubnetId'
272384
272564
  };
272385
272565
  }
272386
272566
  }
272387
272567
  return data;
272388
272568
  }
272569
+ /**
272570
+ * 批量获取云函数详细信息
272571
+ * @param {Object} options
272572
+ * @param {string[]} options.names 云函数名称列表
272573
+ * @param {string} options.envId 环境 ID
272574
+ * @param {string} options.codeSecret
272575
+ * @returns {Promise<IFunctionInfo[]>}
272576
+ */
272577
+ async batchGetFunctionsDetail({ names, envId, codeSecret }) {
272578
+ const data = [];
272579
+ const promises = names.map(name => (async () => {
272580
+ try {
272581
+ const info = await this.getFunctionDetail(name, codeSecret);
272582
+ data.push(info);
272583
+ }
272584
+ catch (e) {
272585
+ throw new error_1.CloudBaseError(`${name} 获取信息失败:${e.message}`);
272586
+ }
272587
+ })());
272588
+ await Promise.all(promises);
272589
+ return data;
272590
+ }
272389
272591
  /**
272390
272592
  * 获取函数日志
272391
272593
  * @deprecated 请使用 getFunctionLogsV2 代替
@@ -272482,6 +272684,33 @@ class FunctionService {
272482
272684
  const res = await this.tcbService.request('GetFunctionLogDetail', params);
272483
272685
  return res;
272484
272686
  }
272687
+ /**
272688
+ * 获取函数的完整调用日志
272689
+ * 该方法会自动完成两步操作:1. 获取日志请求ID列表。 2. 根据ID列表获取每条日志的详细内容。
272690
+ * @param {IFunctionLogOptionsV2} options - 查询选项
272691
+ * @returns {Promise<IFunctionLogDetailRes[]>} 返回包含完整日志详情的数组
272692
+ */
272693
+ async getCompleteFunctionLogs(options) {
272694
+ // 调用 getFunctionLogsV2 获取日志请求ID列表
272695
+ const { name } = options;
272696
+ const logs = await this.getFunctionLogsV2(options);
272697
+ // 如果没有日志,直接返回空数组
272698
+ if (logs.LogList.length === 0) {
272699
+ return [];
272700
+ }
272701
+ const detailPromises = logs.LogList.map(async (log) => {
272702
+ // 对每一个日志ID,调用 getFunctionLogDetail
272703
+ const res = await this.getFunctionLogDetail({
272704
+ logRequestId: log.RequestId,
272705
+ startTime: options.startTime,
272706
+ endTime: options.endTime
272707
+ });
272708
+ return Object.assign(Object.assign({}, res), { RetCode: log.RetCode, FunctionName: name });
272709
+ });
272710
+ // 并发执行所有详情查询,等待它们全部完成
272711
+ const detailedLogs = await Promise.all(detailPromises);
272712
+ return detailedLogs;
272713
+ }
272485
272714
  /**
272486
272715
  * 更新云函数配置
272487
272716
  * @param {ICloudFunction} func 云函数配置
@@ -272617,6 +272846,28 @@ class FunctionService {
272617
272846
  throw new error_1.CloudBaseError(`[${name}] 调用失败:\n${e.message}`);
272618
272847
  }
272619
272848
  }
272849
+ /**
272850
+ * 批量调用云函数
272851
+ * @param {IFunctionBatchOptions} options
272852
+ * @returns {Promise<IFunctionInvokeRes[]>}
272853
+ */
272854
+ async batchInvokeFunctions(options) {
272855
+ const { functions, envId, log = false } = options;
272856
+ const promises = functions.map(func => (async () => {
272857
+ try {
272858
+ const result = await this.invokeFunction(func.name, func.params);
272859
+ if (log) {
272860
+ (0, utils_1.successLog)(`[${func.name}] 调用成功\n响应结果:\n`);
272861
+ console.log(result);
272862
+ }
272863
+ return result;
272864
+ }
272865
+ catch (e) {
272866
+ throw new error_1.CloudBaseError(`${func.name} 函数调用失败:${e.message}`);
272867
+ }
272868
+ })());
272869
+ return Promise.all(promises);
272870
+ }
272620
272871
  /**
272621
272872
  * 复制云函数
272622
272873
  * @param {string} name 云函数名称
@@ -272659,12 +272910,34 @@ class FunctionService {
272659
272910
  TriggerDesc: item.config
272660
272911
  };
272661
272912
  });
272662
- return this.scfService.request('BatchCreateTrigger', {
272663
- FunctionName: name,
272664
- Namespace: namespace,
272665
- Triggers: JSON.stringify(parsedTriggers),
272666
- Count: parsedTriggers.length
272667
- });
272913
+ try {
272914
+ return await this.scfService.request('BatchCreateTrigger', {
272915
+ FunctionName: name,
272916
+ Namespace: namespace,
272917
+ Triggers: JSON.stringify(parsedTriggers),
272918
+ Count: parsedTriggers.length
272919
+ });
272920
+ }
272921
+ catch (e) {
272922
+ throw new error_1.CloudBaseError(`[${name}] 创建触发器失败:${e.message}`, {
272923
+ action: e.action,
272924
+ code: e.code
272925
+ });
272926
+ }
272927
+ }
272928
+ // 批量部署函数触发器
272929
+ async batchCreateTriggers(options) {
272930
+ const { functions, envId } = options;
272931
+ const promises = functions.map(func => (async () => {
272932
+ try {
272933
+ await this.createFunctionTriggers(func.name, func.triggers);
272934
+ (0, utils_1.successLog)(`[${func.name}] 创建云函数触发器成功!`);
272935
+ }
272936
+ catch (e) {
272937
+ throw new error_1.CloudBaseError(e.message);
272938
+ }
272939
+ })());
272940
+ await Promise.all(promises);
272668
272941
  }
272669
272942
  /**
272670
272943
  * 删除云函数触发器
@@ -272674,12 +272947,50 @@ class FunctionService {
272674
272947
  */
272675
272948
  async deleteFunctionTrigger(name, triggerName) {
272676
272949
  const { namespace } = this.getFunctionConfig();
272677
- return this.scfService.request('DeleteTrigger', {
272678
- FunctionName: name,
272679
- Namespace: namespace,
272680
- TriggerName: triggerName,
272681
- Type: 'timer'
272950
+ try {
272951
+ await this.scfService.request('DeleteTrigger', {
272952
+ FunctionName: name,
272953
+ Namespace: namespace,
272954
+ TriggerName: triggerName,
272955
+ Type: 'timer'
272956
+ });
272957
+ (0, utils_1.successLog)(`[${name}] 删除云函数触发器 ${triggerName} 成功!`);
272958
+ }
272959
+ catch (e) {
272960
+ throw new error_1.CloudBaseError(`[${name}] 删除触发器失败:${e.message}`);
272961
+ }
272962
+ }
272963
+ async batchDeleteTriggers(options) {
272964
+ const { functions, envId } = options;
272965
+ const promises = functions.map(func => (async () => {
272966
+ try {
272967
+ func.triggers.forEach(async (trigger) => {
272968
+ await this.deleteFunctionTrigger(func.name, trigger.name);
272969
+ });
272970
+ }
272971
+ catch (e) {
272972
+ throw new error_1.CloudBaseError(e.message);
272973
+ }
272974
+ })());
272975
+ await Promise.all(promises);
272976
+ }
272977
+ /**
272978
+ * 下载云函数代码
272979
+ * @param {IFunctionCodeOptions} options
272980
+ * @returns {Promise<void>}
272981
+ */
272982
+ async downloadFunctionCode(options) {
272983
+ const { destPath, envId, functionName, codeSecret } = options;
272984
+ // 检验路径是否存在
272985
+ (0, utils_1.checkFullAccess)(destPath, true);
272986
+ // 获取下载链接
272987
+ const { Url } = await this.scfService.request('GetFunctionAddress', {
272988
+ FunctionName: functionName,
272989
+ Namespace: envId,
272990
+ CodeSecret: codeSecret
272682
272991
  });
272992
+ // 下载文件
272993
+ return (0, utils_1.downloadAndExtractRemoteZip)(Url, destPath);
272683
272994
  }
272684
272995
  /**
272685
272996
  * 获取云函数代码下载 链接
@@ -272705,6 +273016,68 @@ class FunctionService {
272705
273016
  throw new error_1.CloudBaseError(`[${functionName}] 获取函数代码下载链接失败:\n${e.message}`);
272706
273017
  }
272707
273018
  }
273019
+ // 函数绑定文件层
273020
+ async attachLayer(options) {
273021
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273022
+ let { Layers = [] } = await this.getFunctionDetail(functionName, codeSecret);
273023
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273024
+ // 新加的文件层添加到最后
273025
+ Layers.push({
273026
+ LayerName: layerName,
273027
+ LayerVersion: layerVersion
273028
+ });
273029
+ const res = await this.scfService.request('UpdateFunctionConfiguration', {
273030
+ Layers,
273031
+ Namespace: envId,
273032
+ FunctionName: functionName
273033
+ });
273034
+ return res;
273035
+ }
273036
+ // 函数解绑文件层
273037
+ async unAttachLayer(options) {
273038
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273039
+ let { Layers } = await this.getFunctionDetail(functionName, codeSecret);
273040
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273041
+ const index = Layers.findIndex(item => item.LayerName === layerName && item.LayerVersion === layerVersion);
273042
+ if (index === -1) {
273043
+ throw new error_1.CloudBaseError('层不存在');
273044
+ }
273045
+ // 删除指定的层
273046
+ Layers.splice(index, 1);
273047
+ const apiParams = {
273048
+ Namespace: envId,
273049
+ FunctionName: functionName,
273050
+ Layers: Layers.length > 0 ? Layers : [{
273051
+ LayerName: '',
273052
+ LayerVersion: 0
273053
+ }]
273054
+ };
273055
+ return this.scfService.request('UpdateFunctionConfiguration', apiParams);
273056
+ }
273057
+ // 更新云函数层
273058
+ async updateFunctionLayer(options) {
273059
+ const { envId, functionName, layers } = options;
273060
+ return this.scfService.request('UpdateFunctionConfiguration', {
273061
+ Layers: layers,
273062
+ Namespace: envId,
273063
+ FunctionName: functionName
273064
+ });
273065
+ }
273066
+ // 下载文件层 ZIP 文件
273067
+ async downloadLayer(options) {
273068
+ const { name, version, destPath } = options;
273069
+ const res = await this.scfService.request('GetLayerVersion', {
273070
+ LayerName: name,
273071
+ LayerVersion: version
273072
+ });
273073
+ const url = res === null || res === void 0 ? void 0 : res.Location;
273074
+ const zipPath = path_1.default.join(destPath, `${name}-${version}.zip`);
273075
+ if ((0, utils_1.checkFullAccess)(zipPath)) {
273076
+ throw new error_1.CloudBaseError(`文件已存在:${zipPath}`);
273077
+ }
273078
+ // 下载文件
273079
+ return (0, utils_1.downloadAndExtractRemoteZip)(url, destPath);
273080
+ }
272708
273081
  // 创建文件层版本
272709
273082
  async createLayer(options) {
272710
273083
  const { env } = this.getFunctionConfig();
@@ -272777,7 +273150,7 @@ class FunctionService {
272777
273150
  Limit: limit,
272778
273151
  Offset: offset,
272779
273152
  SearchKey: searchKey,
272780
- SearchSrc: `TCB_${env}`
273153
+ // SearchSrc: `TCB_${env}`
272781
273154
  };
272782
273155
  if (runtime) {
272783
273156
  param.CompatibleRuntime = runtime;
@@ -273106,12 +273479,18 @@ __decorate([
273106
273479
  __decorate([
273107
273480
  (0, utils_1.preLazy)()
273108
273481
  ], FunctionService.prototype, "listFunctions", null);
273482
+ __decorate([
273483
+ (0, utils_1.preLazy)()
273484
+ ], FunctionService.prototype, "listAllFunctions", null);
273109
273485
  __decorate([
273110
273486
  (0, utils_1.preLazy)()
273111
273487
  ], FunctionService.prototype, "deleteFunction", null);
273112
273488
  __decorate([
273113
273489
  (0, utils_1.preLazy)()
273114
273490
  ], FunctionService.prototype, "getFunctionDetail", null);
273491
+ __decorate([
273492
+ (0, utils_1.preLazy)()
273493
+ ], FunctionService.prototype, "batchGetFunctionsDetail", null);
273115
273494
  __decorate([
273116
273495
  (0, utils_1.preLazy)()
273117
273496
  ], FunctionService.prototype, "getFunctionLogs", null);
@@ -273121,6 +273500,9 @@ __decorate([
273121
273500
  __decorate([
273122
273501
  (0, utils_1.preLazy)()
273123
273502
  ], FunctionService.prototype, "getFunctionLogDetail", null);
273503
+ __decorate([
273504
+ (0, utils_1.preLazy)()
273505
+ ], FunctionService.prototype, "getCompleteFunctionLogs", null);
273124
273506
  __decorate([
273125
273507
  (0, utils_1.preLazy)()
273126
273508
  ], FunctionService.prototype, "updateFunctionConfig", null);
@@ -273130,6 +273512,9 @@ __decorate([
273130
273512
  __decorate([
273131
273513
  (0, utils_1.preLazy)()
273132
273514
  ], FunctionService.prototype, "invokeFunction", null);
273515
+ __decorate([
273516
+ (0, utils_1.preLazy)()
273517
+ ], FunctionService.prototype, "batchInvokeFunctions", null);
273133
273518
  __decorate([
273134
273519
  (0, utils_1.preLazy)()
273135
273520
  ], FunctionService.prototype, "copyFunction", null);
@@ -273142,6 +273527,18 @@ __decorate([
273142
273527
  __decorate([
273143
273528
  (0, utils_1.preLazy)()
273144
273529
  ], FunctionService.prototype, "getFunctionDownloadUrl", null);
273530
+ __decorate([
273531
+ (0, utils_1.preLazy)()
273532
+ ], FunctionService.prototype, "attachLayer", null);
273533
+ __decorate([
273534
+ (0, utils_1.preLazy)()
273535
+ ], FunctionService.prototype, "unAttachLayer", null);
273536
+ __decorate([
273537
+ (0, utils_1.preLazy)()
273538
+ ], FunctionService.prototype, "updateFunctionLayer", null);
273539
+ __decorate([
273540
+ (0, utils_1.preLazy)()
273541
+ ], FunctionService.prototype, "downloadLayer", null);
273145
273542
  __decorate([
273146
273543
  (0, utils_1.preLazy)()
273147
273544
  ], FunctionService.prototype, "createLayer", null);