@cloudbase/cloudbase-mcp 2.1.0 → 2.2.0-alpha.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/cli.cjs CHANGED
@@ -102,6 +102,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
102
102
  Object.defineProperty(exports, "__esModule", ({ value: true }));
103
103
  exports.CloudRunService = void 0;
104
104
  exports.codeToZip = codeToZip;
105
+ exports.parseObjectToDiffConfigItem = parseObjectToDiffConfigItem;
105
106
  const archiver_1 = __importDefault(__webpack_require__(99133));
106
107
  const fs_extra_1 = __webpack_require__(21605);
107
108
  const path_1 = __importDefault(__webpack_require__(39902));
@@ -270,7 +271,7 @@ class CloudRunService {
270
271
  /**
271
272
  * 上传部署包
272
273
  */
273
- const zipFile = await codeToZip(targetPath, { installDependency: true });
274
+ const zipFile = await codeToZip(targetPath, { installDependency: (serverConfig === null || serverConfig === void 0 ? void 0 : serverConfig.InstallDependency) !== undefined ? serverConfig.InstallDependency : true });
274
275
  await (0, utils_1.upload)({
275
276
  url: uploadUrl,
276
277
  file: zipFile,
@@ -286,8 +287,14 @@ class CloudRunService {
286
287
  if (await this._checkFunctionExist(serverName)) {
287
288
  // 更新
288
289
  const serverDetail = await this.detail({ serverName });
289
- 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
290
+ 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
290
291
  );
292
+ if ((serverDetail === null || serverDetail === void 0 ? void 0 : serverDetail.ServerConfig.Tag) === 'function:') {
293
+ deployInfo.BuildPacks = {
294
+ LanguageVersion: '20.18',
295
+ RepoLanguage: 'Node.js'
296
+ };
297
+ }
291
298
  deployInfo.ReleaseType = 'FULL';
292
299
  return this._upsertFunction(false, {
293
300
  name: serverName,
@@ -315,7 +322,13 @@ class CloudRunService {
315
322
  RepoLanguage: 'Node.js'
316
323
  };
317
324
  }
318
- 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:' });
325
+ const _serverConfig = Object.assign(Object.assign(Object.assign({ OpenAccessTypes: ['OA', 'PUBLIC', 'MINIAPP'],
326
+ // Cpu: 0,
327
+ // Mem: 0,
328
+ MinNum: 0,
329
+ // MaxNum: 0,
330
+ // PolicyDetails: [],
331
+ 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:' });
319
332
  return this._upsertFunction(true, {
320
333
  name: serverName,
321
334
  deployInfo,
@@ -349,11 +362,12 @@ class CloudRunService {
349
362
  _upsertFunction(isNew, data) {
350
363
  const { name, deployInfo, serverConfig } = data;
351
364
  const envConfig = this.environment.lazyEnvironmentConfig;
365
+ const Items = parseObjectToDiffConfigItem(serverConfig);
352
366
  return this.tcbrService.request(isNew ? 'CreateCloudRunServer' : 'UpdateCloudRunServer', {
353
367
  EnvId: envConfig.EnvId,
354
368
  ServerName: name,
355
369
  DeployInfo: deployInfo,
356
- ServerConfig: serverConfig
370
+ Items,
357
371
  });
358
372
  }
359
373
  }
@@ -426,6 +440,63 @@ async function codeToZip(cwd, options) {
426
440
  await archive.finalize();
427
441
  return bufferPromise;
428
442
  }
443
+ /**
444
+ * 提交参数变化映射
445
+ */
446
+ const SUBMIT_DIFF_MAP = {
447
+ Cpu: 'CpuSpecs',
448
+ Mem: 'MemSpecs',
449
+ OpenAccessTypes: 'AccessTypes',
450
+ EnvParams: 'EnvParam',
451
+ CustomLogs: 'LogPath'
452
+ };
453
+ /**
454
+ * 将 object 参数转为 [{key:"Port", IntValue:80}] 的格式,并且剔除空字符串
455
+ */
456
+ function parseObjectToDiffConfigItem(data) {
457
+ const kvs = Object.entries(data);
458
+ const Items = [];
459
+ kvs.forEach(([k, v]) => {
460
+ const Key = SUBMIT_DIFF_MAP[k] || k;
461
+ if ([
462
+ 'CustomLogs',
463
+ 'EnvParams',
464
+ 'CreateTime',
465
+ 'Dockerfile',
466
+ 'BuildDir',
467
+ 'LogType',
468
+ 'LogSetId',
469
+ 'LogTopicId',
470
+ 'LogParseType',
471
+ 'Tag',
472
+ 'InternalAccess',
473
+ 'InternalDomain',
474
+ 'OperationMode',
475
+ 'SessionAffinity'
476
+ ].includes(k)) {
477
+ !!v && Items.push({ Key, Value: v });
478
+ }
479
+ else if (['MinNum', 'MaxNum', 'InitialDelaySeconds', 'Port'].includes(k)) {
480
+ Items.push({ Key, IntValue: v });
481
+ }
482
+ else if (['HasDockerfile'].includes(k)) {
483
+ Items.push({ Key, BoolValue: v });
484
+ }
485
+ else if (['Cpu', 'Mem'].includes(k)) {
486
+ Items.push({ Key, FloatValue: v });
487
+ }
488
+ else if (['OpenAccessTypes', 'EntryPoint', 'Cmd'].includes(k)) {
489
+ Items.push({ Key, ArrayValue: v });
490
+ }
491
+ else if (['PolicyDetails'].includes(k)) {
492
+ Items.push({ Key, PolicyDetails: v });
493
+ }
494
+ else if (['TimerScale'].includes(k)) {
495
+ Items.push({ Key, TimerScale: v });
496
+ }
497
+ });
498
+ return Items;
499
+ }
429
500
 
430
501
 
431
502
  /***/ }),
@@ -23554,7 +23625,7 @@ async function getCloudBaseManager(options = {}) {
23554
23625
  secretKey,
23555
23626
  envId: finalEnvId || loginEnvId,
23556
23627
  token,
23557
- proxy: process.env.http_proxy
23628
+ proxy: process.env.http_proxy,
23558
23629
  });
23559
23630
  return manager;
23560
23631
  }
@@ -23571,13 +23642,8 @@ async function getCloudBaseManager(options = {}) {
23571
23642
  function createCloudBaseManagerWithOptions(cloudBaseOptions) {
23572
23643
  (0, logger_js_1.debug)('使用传入的 CloudBase 配置创建 manager:', cloudBaseOptions);
23573
23644
  const manager = new manager_node_1.default({
23574
- secretId: cloudBaseOptions.secretId,
23575
- secretKey: cloudBaseOptions.secretKey,
23576
- envId: cloudBaseOptions.envId,
23577
- token: cloudBaseOptions.token,
23645
+ ...cloudBaseOptions,
23578
23646
  proxy: cloudBaseOptions.proxy || process.env.http_proxy,
23579
- region: cloudBaseOptions.region,
23580
- envType: cloudBaseOptions.envType
23581
23647
  });
23582
23648
  return manager;
23583
23649
  }
@@ -48550,7 +48616,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
48550
48616
  exports.cloudBaseRequest = cloudBaseRequest;
48551
48617
  const auth_1 = __webpack_require__(23506);
48552
48618
  const http_request_1 = __webpack_require__(72088);
48553
- const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou'];
48619
+ const SUPPORT_REGIONS = ['ap-shanghai', 'ap-guangzhou', 'ap-singapore'];
48554
48620
  async function cloudBaseRequest(options) {
48555
48621
  // const url = 'https://tcb-admin.tencentcloudapi.com/admin'
48556
48622
  const { config, params = {}, method = 'POST', headers = {} } = options;
@@ -48564,11 +48630,11 @@ async function cloudBaseRequest(options) {
48564
48630
  let internalRegionEndpoint = '';
48565
48631
  if (finalRegion) {
48566
48632
  if (SUPPORT_REGIONS.includes(finalRegion)) {
48567
- internetRegionEndpoint = `${finalRegion}.tcb-api.tencentcloudapi.com`;
48568
- internalRegionEndpoint = `internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48633
+ internetRegionEndpoint = `${envId}.${finalRegion}.tcb-api.tencentcloudapi.com`;
48634
+ internalRegionEndpoint = `${envId}.internal.${finalRegion}.tcb-api.tencentcloudapi.com`;
48569
48635
  }
48570
48636
  else {
48571
- console.warn('当前仅支持上海,广州地域,其他地域默认解析到固定域名(上海地域)');
48637
+ console.warn('当前仅支持上海,广州,新加坡地域,其他地域默认解析到固定域名(上海地域)');
48572
48638
  internetRegionEndpoint = `tcb-api.tencentcloudapi.com`;
48573
48639
  internalRegionEndpoint = `internal.tcb-api.tencentcloudapi.com`;
48574
48640
  }
@@ -90161,19 +90227,20 @@ class EnvService {
90161
90227
  });
90162
90228
  }
90163
90229
  getCos() {
90230
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
90164
90231
  const { secretId, secretKey, token } = this.environment.getAuthConfig();
90165
90232
  const cosConfig = {
90166
90233
  SecretId: secretId,
90167
90234
  SecretKey: secretKey,
90168
90235
  SecurityToken: token,
90169
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90236
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
90170
90237
  };
90171
90238
  if (constant_1.COS_SDK_PROTOCOL) {
90172
90239
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
90173
90240
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
90174
90241
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
90175
90242
  }
90176
- if (constant_1.USE_INTERNAL_ENDPOINT) {
90243
+ if (internalEndpoint) {
90177
90244
  cosConfig.Protocol = 'http:';
90178
90245
  }
90179
90246
  return new cos_nodejs_sdk_v5_1.default(cosConfig);
@@ -135017,7 +135084,7 @@ class TelemetryReporter {
135017
135084
  const nodeVersion = process.version; // Node.js版本
135018
135085
  const arch = os_1.default.arch(); // 系统架构
135019
135086
  // 从构建时注入的版本号获取MCP版本信息
135020
- const mcpVersion = process.env.npm_package_version || "2.1.0" || 0;
135087
+ const mcpVersion = process.env.npm_package_version || "2.2.0-alpha.0" || 0;
135021
135088
  return {
135022
135089
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
135023
135090
  deviceId: this.deviceId,
@@ -179615,6 +179682,7 @@ exports.sleep = sleep;
179615
179682
  exports.upperCaseStringFisrt = upperCaseStringFisrt;
179616
179683
  exports.upperCaseObjKey = upperCaseObjKey;
179617
179684
  exports.fetchTemplates = fetchTemplates;
179685
+ exports.successLog = successLog;
179618
179686
  const archiver_1 = __importDefault(__webpack_require__(99133));
179619
179687
  const crypto_1 = __importDefault(__webpack_require__(55511));
179620
179688
  const fs_extra_1 = __importDefault(__webpack_require__(21605));
@@ -179893,6 +179961,10 @@ const getCompleteTimeRange = (timeRange) => {
179893
179961
  };
179894
179962
  };
179895
179963
  exports.getCompleteTimeRange = getCompleteTimeRange;
179964
+ function successLog(msg) {
179965
+ // 空格,兼容中文字符编码长度问题
179966
+ console.log(`${msg}`);
179967
+ }
179896
179968
 
179897
179969
 
179898
179970
  /***/ }),
@@ -191221,20 +191293,25 @@ function callSuccessCallback(callback, result) {
191221
191293
  /***/ }),
191222
191294
 
191223
191295
  /***/ 65607:
191224
- /***/ ((__unused_webpack_module, exports) => {
191296
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
191225
191297
 
191226
191298
  "use strict";
191227
191299
 
191228
191300
  Object.defineProperty(exports, "__esModule", ({ value: true }));
191229
191301
  exports.CloudBaseContext = void 0;
191302
+ const constant_1 = __webpack_require__(40762);
191230
191303
  class CloudBaseContext {
191231
- constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '' }) {
191304
+ constructor({ secretId = '', secretKey = '', token = '', proxy = '', region = '', envType = '', useInternalEndpoint = undefined }) {
191232
191305
  this.secretId = secretId;
191233
191306
  this.secretKey = secretKey;
191234
191307
  this.token = token;
191235
191308
  this.proxy = proxy;
191236
191309
  this.region = region;
191237
191310
  this.envType = envType;
191311
+ this.useInternalEndpoint = useInternalEndpoint;
191312
+ }
191313
+ isInternalEndpoint() {
191314
+ return this.useInternalEndpoint !== undefined ? this.useInternalEndpoint : constant_1.USE_INTERNAL_ENDPOINT;
191238
191315
  }
191239
191316
  }
191240
191317
  exports.CloudBaseContext = CloudBaseContext;
@@ -200761,7 +200838,7 @@ ${envIdSection}
200761
200838
  ## 环境信息
200762
200839
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
200763
200840
  - Node.js版本: ${process.version}
200764
- - MCP 版本:${process.env.npm_package_version || "2.1.0" || 0}
200841
+ - MCP 版本:${process.env.npm_package_version || "2.2.0-alpha.0" || 0}
200765
200842
  - 系统架构: ${os_1.default.arch()}
200766
200843
  - 时间: ${new Date().toISOString()}
200767
200844
  - 请求ID: ${requestId}
@@ -203653,6 +203730,7 @@ class StorageService {
203653
203730
  * 获取 COS 配置
203654
203731
  */
203655
203732
  getCos(parallel = 20) {
203733
+ const internalEndpoint = this.environment.cloudBaseContext.isInternalEndpoint();
203656
203734
  const { secretId, secretKey, token, proxy } = this.environment.getAuthConfig();
203657
203735
  const cosProxy = process.env.TCB_COS_PROXY;
203658
203736
  const cosConfig = {
@@ -203661,14 +203739,14 @@ class StorageService {
203661
203739
  SecretKey: secretKey,
203662
203740
  Proxy: cosProxy || proxy,
203663
203741
  SecurityToken: token,
203664
- Domain: constant_1.USE_INTERNAL_ENDPOINT ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203742
+ Domain: internalEndpoint ? "{Bucket}.cos-internal.{Region}.tencentcos.cn" /* COS_ENDPOINT.INTERNAL */ : "{Bucket}.cos.{Region}.tencentcos.cn" /* COS_ENDPOINT.PUBLIC */,
203665
203743
  };
203666
203744
  if (constant_1.COS_SDK_PROTOCOL) {
203667
203745
  cosConfig.Protocol = (constant_1.COS_SDK_PROTOCOL.endsWith(':')
203668
203746
  ? constant_1.COS_SDK_PROTOCOL.toLowerCase()
203669
203747
  : constant_1.COS_SDK_PROTOCOL.toLowerCase() + ':');
203670
203748
  }
203671
- if (constant_1.USE_INTERNAL_ENDPOINT) {
203749
+ if (internalEndpoint) {
203672
203750
  cosConfig.Protocol = 'http:';
203673
203751
  }
203674
203752
  // COSSDK 默认开启 KeepAlive,这里提供关闭的方式
@@ -215060,26 +215138,26 @@ const path = __importStar(__webpack_require__(39902));
215060
215138
  const zod_1 = __webpack_require__(21614);
215061
215139
  // CloudBase 模板配置
215062
215140
  const TEMPLATES = {
215063
- "react": {
215141
+ react: {
215064
215142
  description: "React + CloudBase 全栈应用模板",
215065
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip"
215143
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-react-template.zip",
215066
215144
  },
215067
- "vue": {
215145
+ vue: {
215068
215146
  description: "Vue + CloudBase 全栈应用模板",
215069
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip"
215147
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-vue-template.zip",
215070
215148
  },
215071
- "miniprogram": {
215149
+ miniprogram: {
215072
215150
  description: "微信小程序 + 云开发模板",
215073
- url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip"
215151
+ url: "https://static.cloudbase.net/cloudbase-examples/miniprogram-cloudbase-miniprogram-template.zip",
215074
215152
  },
215075
- "uniapp": {
215153
+ uniapp: {
215076
215154
  description: "UniApp + CloudBase 跨端应用模板",
215077
- url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip"
215155
+ url: "https://static.cloudbase.net/cloudbase-examples/universal-cloudbase-uniapp-template.zip",
215078
215156
  },
215079
- "rules": {
215157
+ rules: {
215080
215158
  description: "AI编辑器配置模板(包含所有主流编辑器配置)",
215081
- url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip"
215082
- }
215159
+ url: "https://static.cloudbase.net/cloudbase-examples/web-cloudbase-project.zip",
215160
+ },
215083
215161
  };
215084
215162
  // IDE类型枚举
215085
215163
  const IDE_TYPES = [
@@ -215099,22 +215177,13 @@ const IDE_TYPES = [
215099
215177
  "roocode", // RooCode AI编辑器
215100
215178
  "tongyi-lingma", // 通义灵码
215101
215179
  "trae", // Trae AI编辑器
215102
- "vscode" // Visual Studio Code
215180
+ "vscode", // Visual Studio Code
215103
215181
  ];
215104
215182
  // IDE到文件的映射关系
215105
215183
  const IDE_FILE_MAPPINGS = {
215106
- "cursor": [
215107
- ".cursor/rules/cloudbase-rules.mdc",
215108
- ".cursor/mcp.json"
215109
- ],
215110
- "windsurf": [
215111
- ".windsurf/rules/cloudbase-rules.md"
215112
- ],
215113
- "codebuddy": [
215114
- ".rules/cloudbase-rules.md",
215115
- "CODEBUDDY.md",
215116
- ".mcp.json"
215117
- ],
215184
+ cursor: [".cursor/rules/cloudbase-rules.mdc", ".cursor/mcp.json"],
215185
+ windsurf: [".windsurf/rules/cloudbase-rules.md"],
215186
+ codebuddy: [".rules/cloudbase-rules.md", "CODEBUDDY.md", ".mcp.json"],
215118
215187
  "claude-code": [
215119
215188
  "CLAUDE.md",
215120
215189
  ".mcp.json",
@@ -215123,49 +215192,22 @@ const IDE_FILE_MAPPINGS = {
215123
215192
  ".claude/commands/spec.md",
215124
215193
  ".claude/commands/no_spec.md",
215125
215194
  ],
215126
- "cline": [
215127
- ".clinerules/cloudbase-rules.mdc"
215128
- ],
215129
- "gemini-cli": [
215130
- ".gemini/GEMINI.md",
215131
- ".gemini/settings.json"
215132
- ],
215133
- "opencode": [
215134
- ".opencode.json"
215135
- ],
215136
- "qwen-code": [
215137
- ".qwen/QWEN.md",
215138
- ".qwen/settings.json"
215139
- ],
215195
+ cline: [".clinerules/cloudbase-rules.mdc"],
215196
+ "gemini-cli": [".gemini/GEMINI.md", ".gemini/settings.json"],
215197
+ opencode: [".opencode.json"],
215198
+ "qwen-code": [".qwen/QWEN.md", ".qwen/settings.json"],
215140
215199
  "baidu-comate": [
215141
215200
  ".comate/rules/cloudbase-rules.mdr",
215142
215201
  ".comate/rules/cloudbaase-rules.mdr",
215143
- ".comate/mcp.json"
215144
- ],
215145
- "openai-codex-cli": [
215146
- ".codex/config.toml",
215147
- "AGENTS.md",
215148
- ],
215149
- "augment-code": [
215150
- ".augment-guidelines"
215202
+ ".comate/mcp.json",
215151
215203
  ],
215152
- "github-copilot": [
215153
- ".github/copilot-instructions.md"
215154
- ],
215155
- "roocode": [
215156
- ".roo/rules/cloudbaase-rules.md",
215157
- ".roo/mcp.json"
215158
- ],
215159
- "tongyi-lingma": [
215160
- ".lingma/rules/cloudbaase-rules.md"
215161
- ],
215162
- "trae": [
215163
- ".trae/rules/cloudbase-rules.md"
215164
- ],
215165
- "vscode": [
215166
- ".vscode/mcp.json",
215167
- ".vscode/settings.json"
215168
- ]
215204
+ "openai-codex-cli": [".codex/config.toml", "AGENTS.md"],
215205
+ "augment-code": [".augment-guidelines"],
215206
+ "github-copilot": [".github/copilot-instructions.md"],
215207
+ roocode: [".roo/rules/cloudbaase-rules.md", ".roo/mcp.json"],
215208
+ "tongyi-lingma": [".lingma/rules/cloudbaase-rules.md"],
215209
+ trae: [".trae/rules/cloudbase-rules.md"],
215210
+ vscode: [".vscode/mcp.json", ".vscode/settings.json"],
215169
215211
  };
215170
215212
  // 所有IDE配置文件的完整列表 - 通过IDE_FILE_MAPPINGS计算得出
215171
215213
  const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()));
@@ -215173,51 +215215,87 @@ const ALL_IDE_FILES = Array.from(new Set(Object.values(IDE_FILE_MAPPINGS).flat()
215173
215215
  IDE_FILE_MAPPINGS["all"] = ALL_IDE_FILES;
215174
215216
  // IDE描述映射
215175
215217
  const IDE_DESCRIPTIONS = {
215176
- "all": "所有IDE配置",
215177
- "cursor": "Cursor AI编辑器",
215178
- "windsurf": "WindSurf AI编辑器",
215179
- "codebuddy": "CodeBuddy AI编辑器",
215218
+ all: "所有IDE配置",
215219
+ cursor: "Cursor AI编辑器",
215220
+ windsurf: "WindSurf AI编辑器",
215221
+ codebuddy: "CodeBuddy AI编辑器",
215180
215222
  "claude-code": "Claude Code AI编辑器",
215181
- "cline": "Cline AI编辑器",
215223
+ cline: "Cline AI编辑器",
215182
215224
  "gemini-cli": "Gemini CLI",
215183
- "opencode": "OpenCode AI编辑器",
215225
+ opencode: "OpenCode AI编辑器",
215184
215226
  "qwen-code": "通义灵码",
215185
215227
  "baidu-comate": "百度Comate",
215186
215228
  "openai-codex-cli": "OpenAI Codex CLI",
215187
215229
  "augment-code": "Augment Code",
215188
215230
  "github-copilot": "GitHub Copilot",
215189
- "roocode": "RooCode AI编辑器",
215231
+ roocode: "RooCode AI编辑器",
215190
215232
  "tongyi-lingma": "通义灵码",
215191
- "trae": "Trae AI编辑器",
215192
- "vscode": "Visual Studio Code"
215193
- };
215233
+ trae: "Trae AI编辑器",
215234
+ vscode: "Visual Studio Code",
215235
+ };
215236
+ // INTEGRATION_IDE 环境变量值到 IDE 类型的映射
215237
+ const INTEGRATION_IDE_MAPPING = {
215238
+ Cursor: "cursor",
215239
+ WindSurf: "windsurf",
215240
+ CodeBuddy: "codebuddy",
215241
+ CodeBuddyManual: "codebuddy",
215242
+ CodeBuddyCode: "codebuddy",
215243
+ "Claude Code": "claude-code",
215244
+ CLINE: "cline",
215245
+ "Gemini CLI": "gemini-cli",
215246
+ OpenCode: "opencode",
215247
+ "Qwen Code": "qwen-code",
215248
+ "Baidu Comate": "baidu-comate",
215249
+ "OpenAI Codex CLI": "openai-codex-cli",
215250
+ "Augment Code": "augment-code",
215251
+ "GitHub Copilot": "github-copilot",
215252
+ RooCode: "roocode",
215253
+ "Tongyi Lingma": "tongyi-lingma",
215254
+ Trae: "trae",
215255
+ VSCode: "vscode",
215256
+ };
215257
+ // 根据 INTEGRATION_IDE 环境变量获取默认 IDE 类型
215258
+ function getDefaultIDEFromEnv() {
215259
+ const integrationIDE = process.env.INTEGRATION_IDE;
215260
+ if (integrationIDE) {
215261
+ const mappedIDE = INTEGRATION_IDE_MAPPING[integrationIDE];
215262
+ if (mappedIDE) {
215263
+ return mappedIDE;
215264
+ }
215265
+ }
215266
+ return "all";
215267
+ }
215194
215268
  // 下载文件到临时目录
215195
215269
  async function downloadFile(url, filePath) {
215196
215270
  return new Promise((resolve, reject) => {
215197
- const client = url.startsWith('https:') ? https : http;
215198
- client.get(url, (res) => {
215271
+ const client = url.startsWith("https:") ? https : http;
215272
+ client
215273
+ .get(url, (res) => {
215199
215274
  if (res.statusCode === 200) {
215200
215275
  const file = fs.createWriteStream(filePath);
215201
215276
  res.pipe(file);
215202
- file.on('finish', () => {
215277
+ file.on("finish", () => {
215203
215278
  file.close();
215204
215279
  resolve();
215205
215280
  });
215206
- file.on('error', reject);
215281
+ file.on("error", reject);
215207
215282
  }
215208
215283
  else if (res.statusCode === 302 || res.statusCode === 301) {
215209
215284
  // 处理重定向
215210
215285
  if (res.headers.location) {
215211
- downloadFile(res.headers.location, filePath).then(resolve).catch(reject);
215286
+ downloadFile(res.headers.location, filePath)
215287
+ .then(resolve)
215288
+ .catch(reject);
215212
215289
  }
215213
215290
  else {
215214
- reject(new Error('重定向但没有location header'));
215291
+ reject(new Error("重定向但没有location header"));
215215
215292
  }
215216
215293
  }
215217
215294
  else {
215218
215295
  reject(new Error(`下载失败,状态码: ${res.statusCode}`));
215219
215296
  }
215220
- }).on('error', reject);
215297
+ })
215298
+ .on("error", reject);
215221
215299
  });
215222
215300
  }
215223
215301
  // 解压ZIP文件
@@ -215230,7 +215308,7 @@ async function extractZip(zipPath, extractPath) {
215230
215308
  zip.extractAllTo(extractPath, true);
215231
215309
  }
215232
215310
  catch (error) {
215233
- throw new Error(`解压失败: ${error instanceof Error ? error.message : '未知错误'}`);
215311
+ throw new Error(`解压失败: ${error instanceof Error ? error.message : "未知错误"}`);
215234
215312
  }
215235
215313
  }
215236
215314
  // 获取目录下所有文件的相对路径列表
@@ -215254,7 +215332,7 @@ async function copyFileIfNotExists(src, dest) {
215254
215332
  try {
215255
215333
  // 检查目标文件是否存在
215256
215334
  if (fs.existsSync(dest)) {
215257
- return { copied: false, reason: '文件已存在' };
215335
+ return { copied: false, reason: "文件已存在" };
215258
215336
  }
215259
215337
  // 创建目标目录
215260
215338
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -215263,14 +215341,17 @@ async function copyFileIfNotExists(src, dest) {
215263
215341
  return { copied: true };
215264
215342
  }
215265
215343
  catch (error) {
215266
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215344
+ return {
215345
+ copied: false,
215346
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215347
+ };
215267
215348
  }
215268
215349
  }
215269
215350
  // 复制文件,支持覆盖模式
215270
215351
  // 判断是否应该跳过 README.md 文件
215271
215352
  function shouldSkipReadme(template, destPath, overwrite) {
215272
- const isReadme = path.basename(destPath).toLowerCase() === 'readme.md';
215273
- const isRulesTemplate = template === 'rules';
215353
+ const isReadme = path.basename(destPath).toLowerCase() === "readme.md";
215354
+ const isRulesTemplate = template === "rules";
215274
215355
  const exists = fs.existsSync(destPath);
215275
215356
  return isReadme && isRulesTemplate && exists && !overwrite;
215276
215357
  }
@@ -215279,11 +215360,15 @@ async function copyFile(src, dest, overwrite = false, template) {
215279
215360
  const destExists = fs.existsSync(dest);
215280
215361
  // 检查是否需要跳过 README.md 文件(仅对 rules 模板)
215281
215362
  if (template && shouldSkipReadme(template, dest, overwrite)) {
215282
- return { copied: false, reason: 'README.md 文件已存在,已保护', action: 'protected' };
215363
+ return {
215364
+ copied: false,
215365
+ reason: "README.md 文件已存在,已保护",
215366
+ action: "protected",
215367
+ };
215283
215368
  }
215284
215369
  // 如果目标文件存在且不允许覆盖
215285
215370
  if (destExists && !overwrite) {
215286
- return { copied: false, reason: '文件已存在', action: 'skipped' };
215371
+ return { copied: false, reason: "文件已存在", action: "skipped" };
215287
215372
  }
215288
215373
  // 创建目标目录
215289
215374
  await fsPromises.mkdir(path.dirname(dest), { recursive: true });
@@ -215291,11 +215376,14 @@ async function copyFile(src, dest, overwrite = false, template) {
215291
215376
  await fsPromises.copyFile(src, dest);
215292
215377
  return {
215293
215378
  copied: true,
215294
- action: destExists ? 'overwritten' : 'created'
215379
+ action: destExists ? "overwritten" : "created",
215295
215380
  };
215296
215381
  }
215297
215382
  catch (error) {
215298
- return { copied: false, reason: `复制失败: ${error instanceof Error ? error.message : '未知错误'}` };
215383
+ return {
215384
+ copied: false,
215385
+ reason: `复制失败: ${error instanceof Error ? error.message : "未知错误"}`,
215386
+ };
215299
215387
  }
215300
215388
  }
215301
215389
  // IDE验证函数
@@ -215303,13 +215391,13 @@ function validateIDE(ide) {
215303
215391
  if (ide === "all") {
215304
215392
  return { valid: true };
215305
215393
  }
215306
- const supportedIDEs = IDE_TYPES.filter(type => type !== "all");
215394
+ const supportedIDEs = IDE_TYPES.filter((type) => type !== "all");
215307
215395
  const isValid = supportedIDEs.includes(ide);
215308
215396
  if (!isValid) {
215309
215397
  return {
215310
215398
  valid: false,
215311
215399
  error: `不支持的IDE类型: ${ide}`,
215312
- supportedIDEs: supportedIDEs
215400
+ supportedIDEs: supportedIDEs,
215313
215401
  };
215314
215402
  }
215315
215403
  return { valid: true };
@@ -215324,9 +215412,9 @@ function filterFilesByIDE(files, ide) {
215324
215412
  return files; // 如果找不到映射,返回所有文件
215325
215413
  }
215326
215414
  // 计算需要排除的IDE文件(除了当前IDE需要的文件)
215327
- const filesToExclude = ALL_IDE_FILES.filter(file => !ideFiles.includes(file));
215415
+ const filesToExclude = ALL_IDE_FILES.filter((file) => !ideFiles.includes(file));
215328
215416
  // 排除不需要的IDE配置文件,保留其他所有文件
215329
- return files.filter(file => !filesToExclude.includes(file));
215417
+ return files.filter((file) => !filesToExclude.includes(file));
215330
215418
  }
215331
215419
  // 创建过滤后的目录结构
215332
215420
  async function createFilteredDirectory(extractDir, filteredFiles, ide) {
@@ -215334,7 +215422,7 @@ async function createFilteredDirectory(extractDir, filteredFiles, ide) {
215334
215422
  return extractDir; // 如果选择所有IDE,直接返回原目录
215335
215423
  }
215336
215424
  // 创建新的过滤后目录
215337
- const filteredDir = path.join(path.dirname(extractDir), 'filtered');
215425
+ const filteredDir = path.join(path.dirname(extractDir), "filtered");
215338
215426
  await fsPromises.mkdir(filteredDir, { recursive: true });
215339
215427
  // 只复制过滤后的文件到新目录
215340
215428
  for (const relativePath of filteredFiles) {
@@ -215353,32 +215441,42 @@ function registerSetupTools(server) {
215353
215441
  title: "下载项目模板",
215354
215442
  description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
215355
215443
 
215356
- **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)`,
215444
+ **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-alpha.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215357
215445
  inputSchema: {
215358
- template: zod_1.z.enum(["react", "vue", "miniprogram", "uniapp", "rules"]).describe("要下载的模板类型"),
215359
- ide: zod_1.z.enum(IDE_TYPES).optional().default("all").describe("指定要下载的IDE类型,默认为all(下载所有IDE配置)"),
215360
- overwrite: zod_1.z.boolean().optional().describe("是否覆盖已存在的文件,默认为false(不覆盖)")
215446
+ template: zod_1.z
215447
+ .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
215448
+ .describe("要下载的模板类型"),
215449
+ ide: zod_1.z
215450
+ .enum(IDE_TYPES)
215451
+ .optional()
215452
+ .describe("指定要下载的IDE类型。如果未指定,会根据 INTEGRATION_IDE 环境变量自动选择对应的IDE配置;如果环境变量也未设置,则默认下载所有IDE配置"),
215453
+ overwrite: zod_1.z
215454
+ .boolean()
215455
+ .optional()
215456
+ .describe("是否覆盖已存在的文件,默认为false(不覆盖)"),
215361
215457
  },
215362
215458
  annotations: {
215363
215459
  readOnlyHint: false,
215364
215460
  destructiveHint: false,
215365
215461
  idempotentHint: false,
215366
215462
  openWorldHint: true,
215367
- category: "setup"
215368
- }
215369
- }, async ({ template, ide = "all", overwrite = false }) => {
215463
+ category: "setup",
215464
+ },
215465
+ }, async ({ template, ide, overwrite = false, }) => {
215370
215466
  try {
215467
+ // 如果没有传入 ide 参数,根据 INTEGRATION_IDE 环境变量获取默认值
215468
+ const resolvedIDE = ide ?? getDefaultIDEFromEnv();
215371
215469
  // 验证IDE类型
215372
- const ideValidation = validateIDE(ide);
215470
+ const ideValidation = validateIDE(resolvedIDE);
215373
215471
  if (!ideValidation.valid) {
215374
- const supportedIDEs = ideValidation.supportedIDEs?.join(', ') || '';
215472
+ const supportedIDEs = ideValidation.supportedIDEs?.join(", ") || "";
215375
215473
  return {
215376
215474
  content: [
215377
215475
  {
215378
215476
  type: "text",
215379
- text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`
215380
- }
215381
- ]
215477
+ text: `❌ ${ideValidation.error}\n\n支持的IDE类型: ${supportedIDEs}`,
215478
+ },
215479
+ ],
215382
215480
  };
215383
215481
  }
215384
215482
  const templateConfig = TEMPLATES[template];
@@ -215387,23 +215485,23 @@ function registerSetupTools(server) {
215387
215485
  content: [
215388
215486
  {
215389
215487
  type: "text",
215390
- text: `❌ 不支持的模板类型: ${template}`
215391
- }
215392
- ]
215488
+ text: `❌ 不支持的模板类型: ${template}`,
215489
+ },
215490
+ ],
215393
215491
  };
215394
215492
  }
215395
215493
  // 创建临时目录
215396
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cloudbase-template-'));
215397
- const zipPath = path.join(tempDir, 'template.zip');
215398
- const extractDir = path.join(tempDir, 'extracted');
215494
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "cloudbase-template-"));
215495
+ const zipPath = path.join(tempDir, "template.zip");
215496
+ const extractDir = path.join(tempDir, "extracted");
215399
215497
  // 下载和解压
215400
215498
  await downloadFile(templateConfig.url, zipPath);
215401
215499
  await extractZip(zipPath, extractDir);
215402
215500
  const extractedFiles = await getAllFiles(extractDir);
215403
215501
  // 根据IDE类型过滤文件
215404
- const filteredFiles = filterFilesByIDE(extractedFiles, ide);
215502
+ const filteredFiles = filterFilesByIDE(extractedFiles, resolvedIDE);
215405
215503
  // 创建过滤后的目录结构(当选择特定IDE时)
215406
- const workingDir = await createFilteredDirectory(extractDir, filteredFiles, ide);
215504
+ const workingDir = await createFilteredDirectory(extractDir, filteredFiles, resolvedIDE);
215407
215505
  // 检查是否需要复制到项目目录
215408
215506
  const workspaceFolder = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
215409
215507
  let finalFiles = [];
@@ -215418,7 +215516,7 @@ function registerSetupTools(server) {
215418
215516
  const destPath = path.join(workspaceFolder, relativePath);
215419
215517
  const copyResult = await copyFile(srcPath, destPath, overwrite, template);
215420
215518
  if (copyResult.copied) {
215421
- if (copyResult.action === 'overwritten') {
215519
+ if (copyResult.action === "overwritten") {
215422
215520
  overwrittenCount++;
215423
215521
  }
215424
215522
  else {
@@ -215427,7 +215525,7 @@ function registerSetupTools(server) {
215427
215525
  finalFiles.push(destPath);
215428
215526
  }
215429
215527
  else {
215430
- if (copyResult.action === 'protected') {
215528
+ if (copyResult.action === "protected") {
215431
215529
  protectedCount++;
215432
215530
  }
215433
215531
  else {
@@ -215437,11 +215535,11 @@ function registerSetupTools(server) {
215437
215535
  }
215438
215536
  }
215439
215537
  // 添加IDE过滤信息
215440
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215538
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215441
215539
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 同步完成`);
215442
215540
  results.push(`📁 临时目录: ${workingDir}`);
215443
215541
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215444
- if (ide !== "all") {
215542
+ if (resolvedIDE !== "all") {
215445
215543
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215446
215544
  }
215447
215545
  const stats = [];
@@ -215454,36 +215552,36 @@ function registerSetupTools(server) {
215454
215552
  if (skippedCount > 0)
215455
215553
  stats.push(`跳过 ${skippedCount} 个已存在文件`);
215456
215554
  if (stats.length > 0) {
215457
- results.push(`📊 ${stats.join('')}`);
215555
+ results.push(`📊 ${stats.join("")}`);
215458
215556
  }
215459
215557
  if (overwrite || overwrittenCount > 0 || skippedCount > 0) {
215460
- results.push(`🔄 覆盖模式: ${overwrite ? '启用' : '禁用'}`);
215558
+ results.push(`🔄 覆盖模式: ${overwrite ? "启用" : "禁用"}`);
215461
215559
  }
215462
215560
  }
215463
215561
  else {
215464
- finalFiles = filteredFiles.map(relativePath => path.join(workingDir, relativePath));
215465
- const ideInfo = IDE_DESCRIPTIONS[ide] || ide;
215562
+ finalFiles = filteredFiles.map((relativePath) => path.join(workingDir, relativePath));
215563
+ const ideInfo = IDE_DESCRIPTIONS[resolvedIDE] || resolvedIDE;
215466
215564
  results.push(`✅ ${templateConfig.description} (${ideInfo}) 下载完成`);
215467
215565
  results.push(`📁 保存在临时目录: ${workingDir}`);
215468
215566
  results.push(`🔍 文件过滤: ${extractedFiles.length} → ${filteredFiles.length} 个文件`);
215469
- if (ide !== "all") {
215567
+ if (resolvedIDE !== "all") {
215470
215568
  results.push(`✨ 已过滤IDE配置,仅保留 ${ideInfo} 相关文件`);
215471
215569
  }
215472
- results.push('💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。');
215570
+ results.push("💡 如需将模板(包括隐藏文件)复制到项目目录,请确保复制时包含所有隐藏文件。");
215473
215571
  }
215474
215572
  // 文件路径列表
215475
- results.push('');
215476
- results.push('📋 文件列表:');
215477
- finalFiles.forEach(filePath => {
215573
+ results.push("");
215574
+ results.push("📋 文件列表:");
215575
+ finalFiles.forEach((filePath) => {
215478
215576
  results.push(`${filePath}`);
215479
215577
  });
215480
215578
  return {
215481
215579
  content: [
215482
215580
  {
215483
215581
  type: "text",
215484
- text: results.join('\n')
215485
- }
215486
- ]
215582
+ text: results.join("\n"),
215583
+ },
215584
+ ],
215487
215585
  };
215488
215586
  }
215489
215587
  catch (error) {
@@ -215491,9 +215589,9 @@ function registerSetupTools(server) {
215491
215589
  content: [
215492
215590
  {
215493
215591
  type: "text",
215494
- text: `❌ 下载模板失败: ${error instanceof Error ? error.message : '未知错误'}`
215495
- }
215496
- ]
215592
+ text: `❌ 下载模板失败: ${error instanceof Error ? error.message : "未知错误"}`,
215593
+ },
215594
+ ],
215497
215595
  };
215498
215596
  }
215499
215597
  });
@@ -226399,6 +226497,7 @@ class CloudService {
226399
226497
  this.cloudBaseContext = context;
226400
226498
  }
226401
226499
  get baseUrl() {
226500
+ const internalEndpoint = this.cloudBaseContext.isInternalEndpoint();
226402
226501
  const tcb = process.env.TCB_BASE_URL || 'https://tcb.tencentcloudapi.com';
226403
226502
  const urlMap = {
226404
226503
  tcb,
@@ -226412,7 +226511,7 @@ class CloudService {
226412
226511
  const intranetUrlMap = Object.keys(urlMap).map((service) => ({
226413
226512
  [service]: `https://${service}.internal.tencentcloudapi.com`,
226414
226513
  })).reduce((acc, cur) => (Object.assign(Object.assign({}, acc), cur)), {});
226415
- if (constant_1.USE_INTERNAL_ENDPOINT) {
226514
+ if (internalEndpoint) {
226416
226515
  return intranetUrlMap[this.service];
226417
226516
  }
226418
226517
  if (urlMap[this.service]) {
@@ -270045,7 +270144,7 @@ class CloudBase {
270045
270144
  }
270046
270145
  constructor(config = {}) {
270047
270146
  this.cloudBaseConfig = {};
270048
- let { secretId, secretKey, token, envId, proxy, region, envType } = config;
270147
+ let { secretId, secretKey, token, envId, proxy, region, envType, useInternalEndpoint } = config;
270049
270148
  // config 中传入的 secretId secretkey 必须同时存在
270050
270149
  if ((secretId && !secretKey) || (!secretId && secretKey)) {
270051
270150
  throw new Error('secretId and secretKey must be a pair');
@@ -270057,7 +270156,8 @@ class CloudBase {
270057
270156
  envId,
270058
270157
  envType,
270059
270158
  proxy,
270060
- region
270159
+ region,
270160
+ useInternalEndpoint
270061
270161
  };
270062
270162
  // 初始化 context
270063
270163
  this.context = new context_1.CloudBaseContext(this.cloudBaseConfig);
@@ -270112,6 +270212,9 @@ class CloudBase {
270112
270212
  getManagerConfig() {
270113
270213
  return this.cloudBaseConfig;
270114
270214
  }
270215
+ get isInternalEndpoint() {
270216
+ return this.context.isInternalEndpoint();
270217
+ }
270115
270218
  }
270116
270219
  module.exports = CloudBase;
270117
270220
 
@@ -272190,6 +272293,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
272190
272293
  exports.FunctionService = void 0;
272191
272294
  const fs_1 = __importDefault(__webpack_require__(29021));
272192
272295
  const path_1 = __importDefault(__webpack_require__(39902));
272296
+ const lodash_1 = __importDefault(__webpack_require__(2543));
272193
272297
  const packer_1 = __webpack_require__(5147);
272194
272298
  const error_1 = __webpack_require__(40430);
272195
272299
  const utils_1 = __webpack_require__(62358);
@@ -272436,20 +272540,96 @@ class FunctionService {
272436
272540
  });
272437
272541
  return data;
272438
272542
  }
272543
+ /**
272544
+ * 列出所有函数
272545
+ * @param {IListFunctionOptions} options
272546
+ * @returns {Promise<Record<string, string>[]>}
272547
+ */
272548
+ async listAllFunctions(options) {
272549
+ const allFunctions = [];
272550
+ let currentOffset = 0;
272551
+ const pageSize = 20;
272552
+ const { envId } = options;
272553
+ while (true) {
272554
+ try {
272555
+ const res = await this.scfService.request('ListFunctions', {
272556
+ Namespace: envId,
272557
+ Limit: pageSize,
272558
+ Offset: currentOffset
272559
+ });
272560
+ const { Functions = [], TotalCount } = res;
272561
+ if (Functions.length === 0) {
272562
+ break;
272563
+ }
272564
+ allFunctions.push(...Functions);
272565
+ // 检查是否已获取所有函数
272566
+ if (allFunctions.length >= TotalCount || Functions.length < pageSize) {
272567
+ break;
272568
+ }
272569
+ currentOffset += pageSize;
272570
+ }
272571
+ catch (error) {
272572
+ throw new error_1.CloudBaseError(`获取函数列表失败: ${error.message}`);
272573
+ }
272574
+ }
272575
+ // 格式化数据
272576
+ const data = [];
272577
+ allFunctions.forEach(func => {
272578
+ const { FunctionId, FunctionName, Runtime, AddTime, ModTime, Status } = func;
272579
+ data.push({
272580
+ FunctionId,
272581
+ FunctionName,
272582
+ Runtime,
272583
+ AddTime,
272584
+ ModTime,
272585
+ Status
272586
+ });
272587
+ });
272588
+ return data;
272589
+ }
272439
272590
  /**
272440
272591
  * 删除云函数
272441
272592
  * @param {string} name 云函数名称
272442
272593
  * @param {string} qualifier 需要删除的版本号,不填默认删除函数下全部版本。
272443
272594
  * @returns {Promise<IResponseInfo>}
272444
272595
  */
272445
- async deleteFunction(name, qualifier) {
272596
+ async deleteFunction({ name }) {
272597
+ var _a;
272446
272598
  const { namespace } = this.getFunctionConfig();
272447
- return this.scfService.request('DeleteFunction', {
272599
+ // 检测是否绑定了 API 网关
272600
+ const accessService = this.environment.getAccessService();
272601
+ const res = await accessService.getAccessList({
272602
+ name
272603
+ });
272604
+ // 删除绑定的 API 网关
272605
+ if (((_a = res === null || res === void 0 ? void 0 : res.APISet) === null || _a === void 0 ? void 0 : _a.length) > 0) {
272606
+ await accessService.deleteAccess({
272607
+ name
272608
+ });
272609
+ }
272610
+ await this.scfService.request('DeleteFunction', {
272448
272611
  FunctionName: name,
272449
- Namespace: namespace,
272450
- Qualifier: qualifier
272612
+ Namespace: namespace
272451
272613
  });
272452
272614
  }
272615
+ /**
272616
+ * 批量删除云函数
272617
+ * @param {Object} options
272618
+ * @param {string[]} options.names 云函数名称列表
272619
+ * @returns {Promise<void>}
272620
+ */
272621
+ async batchDeleteFunctions({ names }) {
272622
+ const promises = names.map(name => (async () => {
272623
+ try {
272624
+ await this.deleteFunction({ name });
272625
+ (0, utils_1.successLog)(`[${name}] 函数删除成功!`);
272626
+ }
272627
+ catch (e) {
272628
+ throw new error_1.CloudBaseError(e.message);
272629
+ }
272630
+ })());
272631
+ await Promise.all(promises);
272632
+ }
272453
272633
  /**
272454
272634
  * 获取云函数详细信息
272455
272635
  * @param {string} name 云函数名称
@@ -272484,13 +272664,35 @@ class FunctionService {
272484
272664
  }
272485
272665
  catch (e) {
272486
272666
  data.VpcConfig = {
272487
- vpc: '',
272488
- subnet: ''
272667
+ vpc: 'VpcId',
272668
+ subnet: 'SubnetId'
272489
272669
  };
272490
272670
  }
272491
272671
  }
272492
272672
  return data;
272493
272673
  }
272674
+ /**
272675
+ * 批量获取云函数详细信息
272676
+ * @param {Object} options
272677
+ * @param {string[]} options.names 云函数名称列表
272678
+ * @param {string} options.envId 环境 ID
272679
+ * @param {string} options.codeSecret
272680
+ * @returns {Promise<IFunctionInfo[]>}
272681
+ */
272682
+ async batchGetFunctionsDetail({ names, envId, codeSecret }) {
272683
+ const data = [];
272684
+ const promises = names.map(name => (async () => {
272685
+ try {
272686
+ const info = await this.getFunctionDetail(name, codeSecret);
272687
+ data.push(info);
272688
+ }
272689
+ catch (e) {
272690
+ throw new error_1.CloudBaseError(`${name} 获取信息失败:${e.message}`);
272691
+ }
272692
+ })());
272693
+ await Promise.all(promises);
272694
+ return data;
272695
+ }
272494
272696
  /**
272495
272697
  * 获取函数日志
272496
272698
  * @deprecated 请使用 getFunctionLogsV2 代替
@@ -272587,6 +272789,33 @@ class FunctionService {
272587
272789
  const res = await this.tcbService.request('GetFunctionLogDetail', params);
272588
272790
  return res;
272589
272791
  }
272792
+ /**
272793
+ * 获取函数的完整调用日志
272794
+ * 该方法会自动完成两步操作:1. 获取日志请求ID列表。 2. 根据ID列表获取每条日志的详细内容。
272795
+ * @param {IFunctionLogOptionsV2} options - 查询选项
272796
+ * @returns {Promise<IFunctionLogDetailRes[]>} 返回包含完整日志详情的数组
272797
+ */
272798
+ async getCompleteFunctionLogs(options) {
272799
+ // 调用 getFunctionLogsV2 获取日志请求ID列表
272800
+ const { name } = options;
272801
+ const logs = await this.getFunctionLogsV2(options);
272802
+ // 如果没有日志,直接返回空数组
272803
+ if (logs.LogList.length === 0) {
272804
+ return [];
272805
+ }
272806
+ const detailPromises = logs.LogList.map(async (log) => {
272807
+ // 对每一个日志ID,调用 getFunctionLogDetail
272808
+ const res = await this.getFunctionLogDetail({
272809
+ logRequestId: log.RequestId,
272810
+ startTime: options.startTime,
272811
+ endTime: options.endTime
272812
+ });
272813
+ return Object.assign(Object.assign({}, res), { RetCode: log.RetCode, FunctionName: name });
272814
+ });
272815
+ // 并发执行所有详情查询,等待它们全部完成
272816
+ const detailedLogs = await Promise.all(detailPromises);
272817
+ return detailedLogs;
272818
+ }
272590
272819
  /**
272591
272820
  * 更新云函数配置
272592
272821
  * @param {ICloudFunction} func 云函数配置
@@ -272722,6 +272951,28 @@ class FunctionService {
272722
272951
  throw new error_1.CloudBaseError(`[${name}] 调用失败:\n${e.message}`);
272723
272952
  }
272724
272953
  }
272954
+ /**
272955
+ * 批量调用云函数
272956
+ * @param {IFunctionBatchOptions} options
272957
+ * @returns {Promise<IFunctionInvokeRes[]>}
272958
+ */
272959
+ async batchInvokeFunctions(options) {
272960
+ const { functions, envId, log = false } = options;
272961
+ const promises = functions.map(func => (async () => {
272962
+ try {
272963
+ const result = await this.invokeFunction(func.name, func.params);
272964
+ if (log) {
272965
+ (0, utils_1.successLog)(`[${func.name}] 调用成功\n响应结果:\n`);
272966
+ console.log(result);
272967
+ }
272968
+ return result;
272969
+ }
272970
+ catch (e) {
272971
+ throw new error_1.CloudBaseError(`${func.name} 函数调用失败:${e.message}`);
272972
+ }
272973
+ })());
272974
+ return Promise.all(promises);
272975
+ }
272725
272976
  /**
272726
272977
  * 复制云函数
272727
272978
  * @param {string} name 云函数名称
@@ -272764,12 +273015,34 @@ class FunctionService {
272764
273015
  TriggerDesc: item.config
272765
273016
  };
272766
273017
  });
272767
- return this.scfService.request('BatchCreateTrigger', {
272768
- FunctionName: name,
272769
- Namespace: namespace,
272770
- Triggers: JSON.stringify(parsedTriggers),
272771
- Count: parsedTriggers.length
272772
- });
273018
+ try {
273019
+ return await this.scfService.request('BatchCreateTrigger', {
273020
+ FunctionName: name,
273021
+ Namespace: namespace,
273022
+ Triggers: JSON.stringify(parsedTriggers),
273023
+ Count: parsedTriggers.length
273024
+ });
273025
+ }
273026
+ catch (e) {
273027
+ throw new error_1.CloudBaseError(`[${name}] 创建触发器失败:${e.message}`, {
273028
+ action: e.action,
273029
+ code: e.code
273030
+ });
273031
+ }
273032
+ }
273033
+ // 批量部署函数触发器
273034
+ async batchCreateTriggers(options) {
273035
+ const { functions, envId } = options;
273036
+ const promises = functions.map(func => (async () => {
273037
+ try {
273038
+ await this.createFunctionTriggers(func.name, func.triggers);
273039
+ (0, utils_1.successLog)(`[${func.name}] 创建云函数触发器成功!`);
273040
+ }
273041
+ catch (e) {
273042
+ throw new error_1.CloudBaseError(e.message);
273043
+ }
273044
+ })());
273045
+ await Promise.all(promises);
272773
273046
  }
272774
273047
  /**
272775
273048
  * 删除云函数触发器
@@ -272779,12 +273052,50 @@ class FunctionService {
272779
273052
  */
272780
273053
  async deleteFunctionTrigger(name, triggerName) {
272781
273054
  const { namespace } = this.getFunctionConfig();
272782
- return this.scfService.request('DeleteTrigger', {
272783
- FunctionName: name,
272784
- Namespace: namespace,
272785
- TriggerName: triggerName,
272786
- Type: 'timer'
273055
+ try {
273056
+ await this.scfService.request('DeleteTrigger', {
273057
+ FunctionName: name,
273058
+ Namespace: namespace,
273059
+ TriggerName: triggerName,
273060
+ Type: 'timer'
273061
+ });
273062
+ (0, utils_1.successLog)(`[${name}] 删除云函数触发器 ${triggerName} 成功!`);
273063
+ }
273064
+ catch (e) {
273065
+ throw new error_1.CloudBaseError(`[${name}] 删除触发器失败:${e.message}`);
273066
+ }
273067
+ }
273068
+ async batchDeleteTriggers(options) {
273069
+ const { functions, envId } = options;
273070
+ const promises = functions.map(func => (async () => {
273071
+ try {
273072
+ func.triggers.forEach(async (trigger) => {
273073
+ await this.deleteFunctionTrigger(func.name, trigger.name);
273074
+ });
273075
+ }
273076
+ catch (e) {
273077
+ throw new error_1.CloudBaseError(e.message);
273078
+ }
273079
+ })());
273080
+ await Promise.all(promises);
273081
+ }
273082
+ /**
273083
+ * 下载云函数代码
273084
+ * @param {IFunctionCodeOptions} options
273085
+ * @returns {Promise<void>}
273086
+ */
273087
+ async downloadFunctionCode(options) {
273088
+ const { destPath, envId, functionName, codeSecret } = options;
273089
+ // 检验路径是否存在
273090
+ (0, utils_1.checkFullAccess)(destPath, true);
273091
+ // 获取下载链接
273092
+ const { Url } = await this.scfService.request('GetFunctionAddress', {
273093
+ FunctionName: functionName,
273094
+ Namespace: envId,
273095
+ CodeSecret: codeSecret
272787
273096
  });
273097
+ // 下载文件
273098
+ return (0, utils_1.downloadAndExtractRemoteZip)(Url, destPath);
272788
273099
  }
272789
273100
  /**
272790
273101
  * 获取云函数代码下载 链接
@@ -272810,6 +273121,68 @@ class FunctionService {
272810
273121
  throw new error_1.CloudBaseError(`[${functionName}] 获取函数代码下载链接失败:\n${e.message}`);
272811
273122
  }
272812
273123
  }
273124
+ // 函数绑定文件层
273125
+ async attachLayer(options) {
273126
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273127
+ let { Layers = [] } = await this.getFunctionDetail(functionName, codeSecret);
273128
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273129
+ // 新加的文件层添加到最后
273130
+ Layers.push({
273131
+ LayerName: layerName,
273132
+ LayerVersion: layerVersion
273133
+ });
273134
+ const res = await this.scfService.request('UpdateFunctionConfiguration', {
273135
+ Layers,
273136
+ Namespace: envId,
273137
+ FunctionName: functionName
273138
+ });
273139
+ return res;
273140
+ }
273141
+ // 函数解绑文件层
273142
+ async unAttachLayer(options) {
273143
+ const { envId, functionName, layerName, layerVersion, codeSecret } = options;
273144
+ let { Layers } = await this.getFunctionDetail(functionName, codeSecret);
273145
+ Layers = Layers.map(item => lodash_1.default.pick(item, ['LayerName', 'LayerVersion']));
273146
+ const index = Layers.findIndex(item => item.LayerName === layerName && item.LayerVersion === layerVersion);
273147
+ if (index === -1) {
273148
+ throw new error_1.CloudBaseError('层不存在');
273149
+ }
273150
+ // 删除指定的层
273151
+ Layers.splice(index, 1);
273152
+ const apiParams = {
273153
+ Namespace: envId,
273154
+ FunctionName: functionName,
273155
+ Layers: Layers.length > 0 ? Layers : [{
273156
+ LayerName: '',
273157
+ LayerVersion: 0
273158
+ }]
273159
+ };
273160
+ return this.scfService.request('UpdateFunctionConfiguration', apiParams);
273161
+ }
273162
+ // 更新云函数层
273163
+ async updateFunctionLayer(options) {
273164
+ const { envId, functionName, layers } = options;
273165
+ return this.scfService.request('UpdateFunctionConfiguration', {
273166
+ Layers: layers,
273167
+ Namespace: envId,
273168
+ FunctionName: functionName
273169
+ });
273170
+ }
273171
+ // 下载文件层 ZIP 文件
273172
+ async downloadLayer(options) {
273173
+ const { name, version, destPath } = options;
273174
+ const res = await this.scfService.request('GetLayerVersion', {
273175
+ LayerName: name,
273176
+ LayerVersion: version
273177
+ });
273178
+ const url = res === null || res === void 0 ? void 0 : res.Location;
273179
+ const zipPath = path_1.default.join(destPath, `${name}-${version}.zip`);
273180
+ if ((0, utils_1.checkFullAccess)(zipPath)) {
273181
+ throw new error_1.CloudBaseError(`文件已存在:${zipPath}`);
273182
+ }
273183
+ // 下载文件
273184
+ return (0, utils_1.downloadAndExtractRemoteZip)(url, destPath);
273185
+ }
272813
273186
  // 创建文件层版本
272814
273187
  async createLayer(options) {
272815
273188
  const { env } = this.getFunctionConfig();
@@ -272882,7 +273255,7 @@ class FunctionService {
272882
273255
  Limit: limit,
272883
273256
  Offset: offset,
272884
273257
  SearchKey: searchKey,
272885
- SearchSrc: `TCB_${env}`
273258
+ // SearchSrc: `TCB_${env}`
272886
273259
  };
272887
273260
  if (runtime) {
272888
273261
  param.CompatibleRuntime = runtime;
@@ -273211,12 +273584,18 @@ __decorate([
273211
273584
  __decorate([
273212
273585
  (0, utils_1.preLazy)()
273213
273586
  ], FunctionService.prototype, "listFunctions", null);
273587
+ __decorate([
273588
+ (0, utils_1.preLazy)()
273589
+ ], FunctionService.prototype, "listAllFunctions", null);
273214
273590
  __decorate([
273215
273591
  (0, utils_1.preLazy)()
273216
273592
  ], FunctionService.prototype, "deleteFunction", null);
273217
273593
  __decorate([
273218
273594
  (0, utils_1.preLazy)()
273219
273595
  ], FunctionService.prototype, "getFunctionDetail", null);
273596
+ __decorate([
273597
+ (0, utils_1.preLazy)()
273598
+ ], FunctionService.prototype, "batchGetFunctionsDetail", null);
273220
273599
  __decorate([
273221
273600
  (0, utils_1.preLazy)()
273222
273601
  ], FunctionService.prototype, "getFunctionLogs", null);
@@ -273226,6 +273605,9 @@ __decorate([
273226
273605
  __decorate([
273227
273606
  (0, utils_1.preLazy)()
273228
273607
  ], FunctionService.prototype, "getFunctionLogDetail", null);
273608
+ __decorate([
273609
+ (0, utils_1.preLazy)()
273610
+ ], FunctionService.prototype, "getCompleteFunctionLogs", null);
273229
273611
  __decorate([
273230
273612
  (0, utils_1.preLazy)()
273231
273613
  ], FunctionService.prototype, "updateFunctionConfig", null);
@@ -273235,6 +273617,9 @@ __decorate([
273235
273617
  __decorate([
273236
273618
  (0, utils_1.preLazy)()
273237
273619
  ], FunctionService.prototype, "invokeFunction", null);
273620
+ __decorate([
273621
+ (0, utils_1.preLazy)()
273622
+ ], FunctionService.prototype, "batchInvokeFunctions", null);
273238
273623
  __decorate([
273239
273624
  (0, utils_1.preLazy)()
273240
273625
  ], FunctionService.prototype, "copyFunction", null);
@@ -273247,6 +273632,18 @@ __decorate([
273247
273632
  __decorate([
273248
273633
  (0, utils_1.preLazy)()
273249
273634
  ], FunctionService.prototype, "getFunctionDownloadUrl", null);
273635
+ __decorate([
273636
+ (0, utils_1.preLazy)()
273637
+ ], FunctionService.prototype, "attachLayer", null);
273638
+ __decorate([
273639
+ (0, utils_1.preLazy)()
273640
+ ], FunctionService.prototype, "unAttachLayer", null);
273641
+ __decorate([
273642
+ (0, utils_1.preLazy)()
273643
+ ], FunctionService.prototype, "updateFunctionLayer", null);
273644
+ __decorate([
273645
+ (0, utils_1.preLazy)()
273646
+ ], FunctionService.prototype, "downloadLayer", null);
273250
273647
  __decorate([
273251
273648
  (0, utils_1.preLazy)()
273252
273649
  ], FunctionService.prototype, "createLayer", null);