@cloudbase/manager-node 5.8.0-beta.2 → 5.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,32 @@
1
+ ## @cloudbase/manager-node v5.8.0 版本发布 🚀(2026-08-20)
2
+
3
+ - 新增 声明式部署编排(hosting 本地构建/gateway 域名绑定/certId 自动查询)
4
+ - 新增 增加 HTTP 服务路由预校验和 SSL 证书查询能力
5
+ - 新增 统一镜像配置校验契约
6
+ - 新增 完善企业版 TCR 云构建链路
7
+ - 新增 补强 Python 部署上下文与检查
8
+ - 新增 validate explicit personal TCR credentials
9
+ - 新增 纳入 database 迁移到声明式编排
10
+ - 重构 降低配置守卫圈复杂度
11
+ - 重构 统一 FunctionDeployer 并迁移镜像部署实现
12
+ - 修复 clarify local default tag
13
+ - 修复 improve cloud build preflight and TCR guidance
14
+ - 修复 移除自动删除重建授权语义
15
+ - 修复 python deploy lint
16
+ - 修复 让云端镜像构建配置真实生效
17
+ - 修复 处理 HTTP 协议规划器 AI 类型安全评审
18
+ - 修复默认 HTTP 协议被误判为需要重建
19
+ - 修复 修正 image 策略 imageType 字段路径导致个人版镜像误判
20
+ - 补充 codeSecret 统一部署契约回归
21
+
22
+ ---
23
+
24
+ ## @cloudbase/manager-node v5.7.0 版本发布 🚀(2026-08-13)
25
+
26
+
27
+
28
+ ---
29
+
1
30
  ## @cloudbase/manager-node v5.6.8 版本发布 🚀(2026-08-11)
2
31
 
3
32
  - 新增 封装 DescribeReleaseOrder 接口
package/lib/env/index.js CHANGED
@@ -28,6 +28,7 @@ class EnvService {
28
28
  this.tcbService = new utils_1.CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08');
29
29
  this.commonService = environment.getCommonService('lowcode', '2021-01-08');
30
30
  this.billingService = new billing_1.BillingService(environment.cloudBaseContext);
31
+ this.certificateCloudService = new utils_1.CloudService(environment.cloudBaseContext, 'ssl', '2019-12-05');
31
32
  this.tokenCache = new Map();
32
33
  }
33
34
  /**
@@ -769,6 +770,23 @@ class EnvService {
769
770
  async describeCreditsUsageDetail(params) {
770
771
  return this.cloudService.request('DescribeCreditsUsageDetail', Object.assign({}, params));
771
772
  }
773
+ /**
774
+ * 获取当前凭证有权限访问的 SSL 证书列表。
775
+ *
776
+ * 证书用于自定义域名 HTTPS 配置,本接口不依赖 CloudBase 环境信息。
777
+ * @param {DescribeCertificatesParams} params 查询参数
778
+ * @returns {Promise<DescribeCertificatesRes>}
779
+ */
780
+ async describeCertificates(params = {}) {
781
+ if (params.Offset !== undefined && (!Number.isInteger(params.Offset) || params.Offset < 0)) {
782
+ throw new error_1.CloudBaseError('Offset 必须是大于等于 0 的整数');
783
+ }
784
+ if (params.Limit !== undefined &&
785
+ (!Number.isInteger(params.Limit) || params.Limit < 1 || params.Limit > 1000)) {
786
+ throw new error_1.CloudBaseError('Limit 必须是 1 至 1000 的整数');
787
+ }
788
+ return this.certificateCloudService.request('DescribeCertificates', params);
789
+ }
772
790
  /**
773
791
  * 查询HTTP访问服务域名路由信息
774
792
  * @param {DescribeHttpServiceRouteParams} params 查询参数
@@ -777,6 +795,15 @@ class EnvService {
777
795
  async describeHttpServiceRoute(params) {
778
796
  return this.cloudService.request('DescribeHTTPServiceRoute', Object.assign({}, params));
779
797
  }
798
+ /**
799
+ * 校验HTTP访问服务域名路由
800
+ * 此操作为只读预检,不会创建任何资源。
801
+ * @param {VerifyHttpServiceRouteParams} params 校验参数
802
+ * @returns {Promise<VerifyHttpServiceRouteRes>}
803
+ */
804
+ async verifyHttpServiceRoute(params) {
805
+ return this.cloudService.request('VerifyHTTPServiceRoute', Object.assign({}, params));
806
+ }
780
807
  /**
781
808
  * 创建HTTP访问服务域名路由
782
809
  * @param {CreateHttpServiceRouteParams} params 创建参数
@@ -126,7 +126,9 @@ function formatImageDeploymentErrorMessage(error, imageConfig) {
126
126
  const isEnterprise = (imageConfig === null || imageConfig === void 0 ? void 0 : imageConfig.imageType) === 'enterprise';
127
127
  const isEnterpriseImageNotFound = haystack.includes('resourcenotfound.image') ||
128
128
  haystack.includes('describe images enterprise resource not found');
129
- if (!isEnterprise || !isEnterpriseImageNotFound || message.includes(exports.ENTERPRISE_IMAGE_REGION_GUIDANCE)) {
129
+ if (!isEnterprise ||
130
+ !isEnterpriseImageNotFound ||
131
+ message.includes(exports.ENTERPRISE_IMAGE_REGION_GUIDANCE)) {
130
132
  return message;
131
133
  }
132
134
  return `${message}\n提示:${exports.ENTERPRISE_IMAGE_REGION_GUIDANCE}`;
@@ -140,25 +142,25 @@ function configToParams(options) {
140
142
  // key: 小写用于匹配,value: PascalCase 用于输出
141
143
  const AUTO_CONVERT_FIELDS = {
142
144
  // 基础配置
143
- 'description': 'Description',
144
- 'memorysize': 'MemorySize',
145
- 'timeout': 'Timeout',
146
- 'runtime': 'Runtime',
147
- 'type': 'Type', // Event/HTTP
148
- 'role': 'Role',
145
+ description: 'Description',
146
+ memorysize: 'MemorySize',
147
+ timeout: 'Timeout',
148
+ runtime: 'Runtime',
149
+ type: 'Type', // Event/HTTP
150
+ role: 'Role',
149
151
  // 日志配置
150
- 'clslogsetid': 'ClsLogsetId',
151
- 'clstopicid': 'ClsTopicId',
152
+ clslogsetid: 'ClsLogsetId',
153
+ clstopicid: 'ClsTopicId',
152
154
  // 高级配置
153
- 'deadletterconfig': 'DeadLetterConfig',
154
- 'publicnetconfig': 'PublicNetConfig',
155
- 'cfsconfig': 'CfsConfig',
156
- 'inittimeout': 'InitTimeout',
157
- 'tags': 'Tags',
155
+ deadletterconfig: 'DeadLetterConfig',
156
+ publicnetconfig: 'PublicNetConfig',
157
+ cfsconfig: 'CfsConfig',
158
+ inittimeout: 'InitTimeout',
159
+ tags: 'Tags',
158
160
  // 注意:asyncRunEnable/traceEnable/autoDeployClsTopicIndex/autoCreateClsTopic/dnsCache
159
161
  // 需要 'TRUE'/'FALSE' 字符串,在特殊处理阶段处理
160
- 'protocoltype': 'ProtocolType', // WS
161
- 'intranetconfig': 'IntranetConfig',
162
+ protocoltype: 'ProtocolType', // WS
163
+ intranetconfig: 'IntranetConfig'
162
164
  };
163
165
  let params = Object.assign(Object.assign({}, baseParams), { FunctionName: func.name });
164
166
  // 第一阶段:白名单字段自动转换(大小写不敏感,统一输出 PascalCase)
@@ -184,11 +186,11 @@ function configToParams(options) {
184
186
  // 3. 需要 'TRUE'/'FALSE' 字符串的布尔字段统一处理(大小写不敏感)
185
187
  // key: 小写用于匹配,value: PascalCase 用于输出
186
188
  const BOOLEAN_STRING_FIELDS = {
187
- 'asyncrunenable': 'AsyncRunEnable', // 异步属性
188
- 'traceenable': 'TraceEnable', // 事件追踪
189
- 'autodeployclstopicindex': 'AutoDeployClsTopicIndex', // 自动创建 CLS 索引
190
- 'autocreateclstopic': 'AutoCreateClsTopic', // 自动创建 CLS 主题
191
- 'dnscache': 'DnsCache', // Dns 缓存
189
+ asyncrunenable: 'AsyncRunEnable', // 异步属性
190
+ traceenable: 'TraceEnable', // 事件追踪
191
+ autodeployclstopicindex: 'AutoDeployClsTopicIndex', // 自动创建 CLS 索引
192
+ autocreateclstopic: 'AutoCreateClsTopic', // 自动创建 CLS 主题
193
+ dnscache: 'DnsCache' // Dns 缓存
192
194
  };
193
195
  for (const key of Object.keys(func)) {
194
196
  const lowerKey = key.toLowerCase();
@@ -352,7 +354,7 @@ class FunctionService {
352
354
  // ENABLE_TCBF 开启时,runtime 适配 tcb 风格
353
355
  if (this.useTcbFunctionApi) {
354
356
  if (!func.runtime) {
355
- params.Runtime = 'Node.js 24.14';
357
+ params.Runtime = 'Nodejs24.14';
356
358
  }
357
359
  }
358
360
  const customCode = code;
@@ -360,7 +362,9 @@ class FunctionService {
360
362
  const funcImageCode = (_a = params.Code) === null || _a === void 0 ? void 0 : _a.ImageConfig;
361
363
  // 根据部署方式处理 Code 参数
362
364
  // 优先级:deployMode=image > 显式传入 code > 原有自动打包逻辑(base64Code/functionPath/functionRootPath)
363
- const isImageDeploy = deployMode === 'image' || Boolean(customImageCode) || (!deployMode && Boolean(funcImageCode));
365
+ const isImageDeploy = deployMode === 'image' ||
366
+ Boolean(customImageCode) ||
367
+ (!deployMode && Boolean(funcImageCode));
364
368
  if (isImageDeploy) {
365
369
  // 镜像部署优先使用显式 code.ImageConfig;未传时回退到 func.imageConfig(configToParams 生成)
366
370
  if (customImageCode) {
@@ -580,9 +584,7 @@ class FunctionService {
580
584
  */
581
585
  async deleteFunction(name) {
582
586
  var _a;
583
- const funcName = typeof name === 'string'
584
- ? name
585
- : name === null || name === void 0 ? void 0 : name.name;
587
+ const funcName = typeof name === 'string' ? name : name === null || name === void 0 ? void 0 : name.name;
586
588
  const { namespace } = this.getFunctionConfig();
587
589
  // 检测是否绑定了 API 网关
588
590
  const accessService = this.environment.getAccessService();
@@ -682,50 +684,50 @@ class FunctionService {
682
684
  return data;
683
685
  }
684
686
  /**
685
- * 获取函数日志
686
- * @deprecated 底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
687
- * @param {{
688
- * name: string
689
- * offset: number
690
- * limit: number
691
- * order: string
692
- * orderBy: string
693
- * startTime: string
694
- * endTime: string
695
- * requestId: string
696
- * }} options
697
- * @returns {Promise<IFunctionLogRes>}
698
- */
687
+ * 获取函数日志
688
+ * @deprecated 底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
689
+ * @param {{
690
+ * name: string
691
+ * offset: number
692
+ * limit: number
693
+ * order: string
694
+ * orderBy: string
695
+ * startTime: string
696
+ * endTime: string
697
+ * requestId: string
698
+ * }} options
699
+ * @returns {Promise<IFunctionLogRes>}
700
+ */
699
701
  async getFunctionLogs(_options) {
700
702
  throw new error_1.CloudBaseError('getFunctionLogs 已废弃:底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志');
701
703
  }
702
704
  /**
703
- * 获取函数日志 ID 列表
704
- * @deprecated 底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
705
- * @param {{
706
- * name: string
707
- * offset: number
708
- * limit: number
709
- * startTime: string
710
- * endTime: string
711
- * requestId: string
712
- * qualifier: string
713
- * }} options
714
- * @returns {Promise<IFunctionLogResV2>}
715
- */
705
+ * 获取函数日志 ID 列表
706
+ * @deprecated 底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
707
+ * @param {{
708
+ * name: string
709
+ * offset: number
710
+ * limit: number
711
+ * startTime: string
712
+ * endTime: string
713
+ * requestId: string
714
+ * qualifier: string
715
+ * }} options
716
+ * @returns {Promise<IFunctionLogResV2>}
717
+ */
716
718
  async getFunctionLogsV2(_options) {
717
719
  throw new error_1.CloudBaseError('getFunctionLogsV2 已废弃:底层 GetFunctionLogs 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志');
718
720
  }
719
721
  /**
720
- * 根据函数日志 ID 查询日志详情
721
- * @deprecated 底层 GetFunctionLogDetail 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
722
- * @param {{
723
- * startTime: string
724
- * endTime: string
725
- * logRequestId: string
726
- * }} options
727
- * @returns {Promise<IFunctionLogDetailRes>}
728
- */
722
+ * 根据函数日志 ID 查询日志详情
723
+ * @deprecated 底层 GetFunctionLogDetail 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志
724
+ * @param {{
725
+ * startTime: string
726
+ * endTime: string
727
+ * logRequestId: string
728
+ * }} options
729
+ * @returns {Promise<IFunctionLogDetailRes>}
730
+ */
729
731
  async getFunctionLogDetail(_options) {
730
732
  throw new error_1.CloudBaseError('getFunctionLogDetail 已废弃:底层 GetFunctionLogDetail 接口已下线,请使用 env.getLogService().searchClsLog() 查询云函数日志');
731
733
  }
@@ -752,22 +754,22 @@ class FunctionService {
752
754
  // 注意:Runtime, Handler, Code, Type, ProtocolType 只能在 CreateFunction 时指定
753
755
  // key: 小写用于匹配,value: PascalCase 用于输出
754
756
  const UPDATE_CONFIG_FIELDS = {
755
- 'description': 'Description',
756
- 'memorysize': 'MemorySize',
757
- 'timeout': 'Timeout',
758
- 'role': 'Role',
757
+ description: 'Description',
758
+ memorysize: 'MemorySize',
759
+ timeout: 'Timeout',
760
+ role: 'Role',
759
761
  // 日志配置
760
- 'clslogsetid': 'ClsLogsetId',
761
- 'clstopicid': 'ClsTopicId',
762
+ clslogsetid: 'ClsLogsetId',
763
+ clstopicid: 'ClsTopicId',
762
764
  // 高级配置
763
- 'deadletterconfig': 'DeadLetterConfig',
764
- 'publicnetconfig': 'PublicNetConfig',
765
- 'cfsconfig': 'CfsConfig',
766
- 'inittimeout': 'InitTimeout',
765
+ deadletterconfig: 'DeadLetterConfig',
766
+ publicnetconfig: 'PublicNetConfig',
767
+ cfsconfig: 'CfsConfig',
768
+ inittimeout: 'InitTimeout',
767
769
  // 注意:asyncRunEnable/traceEnable/autoDeployClsTopicIndex/autoCreateClsTopic
768
770
  // 只能在 CreateFunction 时设置,UpdateFunctionConfiguration 不支持
769
771
  // 注意:dnsCache 需要 'TRUE'/'FALSE' 字符串,在特殊处理阶段处理
770
- 'intranetconfig': 'IntranetConfig',
772
+ intranetconfig: 'IntranetConfig'
771
773
  };
772
774
  const { TopicId, LogsetId } = this.getClsServiceConfig();
773
775
  // 构建参数
@@ -923,13 +925,14 @@ class FunctionService {
923
925
  if (func.installDependency !== undefined) {
924
926
  installDependency = toBooleanString(func.installDependency);
925
927
  }
926
- const codeParams = customCode || await this.getCodeParams({
927
- func,
928
- functionPath,
929
- functionRootPath,
930
- base64Code,
931
- deployMode
932
- }, installDependency);
928
+ const codeParams = customCode ||
929
+ (await this.getCodeParams({
930
+ func,
931
+ functionPath,
932
+ functionRootPath,
933
+ base64Code,
934
+ deployMode
935
+ }, installDependency));
933
936
  const params = {
934
937
  FunctionName: funcName,
935
938
  [this.namespaceParamKey]: namespace,
@@ -1246,10 +1249,14 @@ class FunctionService {
1246
1249
  const apiParams = {
1247
1250
  Namespace: envId,
1248
1251
  FunctionName: functionName,
1249
- Layers: Layers.length > 0 ? Layers : [{
1250
- LayerName: '',
1251
- LayerVersion: 0
1252
- }]
1252
+ Layers: Layers.length > 0
1253
+ ? Layers
1254
+ : [
1255
+ {
1256
+ LayerName: '',
1257
+ LayerVersion: 0
1258
+ }
1259
+ ]
1253
1260
  };
1254
1261
  return this.scfService.request('UpdateFunctionConfiguration', apiParams);
1255
1262
  }
@@ -1348,7 +1355,7 @@ class FunctionService {
1348
1355
  let param = {
1349
1356
  Limit: limit,
1350
1357
  Offset: offset,
1351
- SearchKey: searchKey,
1358
+ SearchKey: searchKey
1352
1359
  // SearchSrc: `TCB_${env}`
1353
1360
  };
1354
1361
  if (runtime) {
@@ -1557,7 +1564,7 @@ class FunctionService {
1557
1564
  Bucket: `${regionPrefix}tempcos-${constant_1.SCF_TEMP_COS.APPID}`,
1558
1565
  Key: tempCosObjectName,
1559
1566
  Region: region,
1560
- FilePath: zipFilePath,
1567
+ FilePath: zipFilePath
1561
1568
  };
1562
1569
  const cos = new cos_nodejs_sdk_v5_1.default({
1563
1570
  getAuthorization: function (options, callback) {
@@ -1657,7 +1664,7 @@ class FunctionService {
1657
1664
  // 直接传入 base64Code 的情况,校验大小
1658
1665
  // ZipFile 上传大小上限 1.5MB,base64 编码后长度约为原始大小的 4/3
1659
1666
  const MAX_ZIP_SIZE = 1.5 * 1024 * 1024; // 1.5MB
1660
- const MAX_BASE64_LENGTH = Math.floor(MAX_ZIP_SIZE * 4 / 3); // ≈ 2097152
1667
+ const MAX_BASE64_LENGTH = Math.floor((MAX_ZIP_SIZE * 4) / 3); // ≈ 2097152
1661
1668
  if ((base64Code === null || base64Code === void 0 ? void 0 : base64Code.length) > MAX_BASE64_LENGTH) {
1662
1669
  throw new error_1.CloudBaseError('ZipFile 上传不能大于 1.5MB,请使用 COS 上传方式');
1663
1670
  }
@@ -1771,10 +1778,10 @@ class FunctionService {
1771
1778
  // 兜底从 Storages[0] 的 AppId 或 Bucket 名提取
1772
1779
  // COS Bucket 格式: {BucketName}-{APPID},APPID 为纯数字
1773
1780
  const storage = (_c = envConfig.Storages) === null || _c === void 0 ? void 0 : _c[0];
1774
- const appId = ((_d = envConfig.UserInfo) === null || _d === void 0 ? void 0 : _d.AppId)
1775
- || (storage === null || storage === void 0 ? void 0 : storage.AppId)
1776
- || ((_f = (_e = storage === null || storage === void 0 ? void 0 : storage.Bucket) === null || _e === void 0 ? void 0 : _e.match(/-(\d+)$/)) === null || _f === void 0 ? void 0 : _f[1])
1777
- || '';
1781
+ const appId = ((_d = envConfig.UserInfo) === null || _d === void 0 ? void 0 : _d.AppId) ||
1782
+ (storage === null || storage === void 0 ? void 0 : storage.AppId) ||
1783
+ ((_f = (_e = storage === null || storage === void 0 ? void 0 : storage.Bucket) === null || _e === void 0 ? void 0 : _e.match(/-(\d+)$/)) === null || _f === void 0 ? void 0 : _f[1]) ||
1784
+ '';
1778
1785
  const { proxy } = this.environment.cloudBaseContext;
1779
1786
  return {
1780
1787
  proxy,
@@ -131,7 +131,7 @@ class HostingService {
131
131
  * @param options
132
132
  */
133
133
  async uploadFiles(options) {
134
- const { localPath, cloudPath, files = [], onProgress, onFileFinish, parallel = 20, ignore = ['.DS_Store'], retryCount, retryInterval } = options;
134
+ const { localPath, cloudPath, entryFiles, files = [], onProgress, onFileFinish, parallel = 20, ignore = ['.DS_Store'], retryCount, retryInterval, verify = false, safe = false, prune = false } = options;
135
135
  const hosting = await this.checkStatus();
136
136
  const { Bucket, Regoin } = hosting;
137
137
  const storageService = await this.environment.getStorageService();
@@ -142,9 +142,29 @@ class HostingService {
142
142
  // 检查路径是否存在
143
143
  (0, utils_1.checkReadable)(resolvePath, true);
144
144
  if ((0, utils_1.isDirectory)(resolvePath)) {
145
+ if (safe || verify || prune) {
146
+ return storageService.uploadDirectoryConsistent({
147
+ localPath: resolvePath,
148
+ cloudPath,
149
+ entries: entryFiles,
150
+ bucket: Bucket,
151
+ region: Regoin,
152
+ onProgress,
153
+ onFileFinish,
154
+ fileId: false,
155
+ ignore,
156
+ parallel,
157
+ retryCount,
158
+ retryInterval,
159
+ verify,
160
+ safe,
161
+ prune
162
+ });
163
+ }
145
164
  return storageService.uploadDirectoryCustom({
146
165
  localPath: resolvePath,
147
166
  cloudPath,
167
+ entryFiles,
148
168
  bucket: Bucket,
149
169
  region: Regoin,
150
170
  onProgress,
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.md5File = md5File;
7
+ exports.splitEntryUploadFiles = splitEntryUploadFiles;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const path_1 = __importDefault(require("path"));
11
+ /**
12
+ * 流式计算文件 MD5(32 位小写十六进制),不将整个文件读入内存
13
+ */
14
+ function md5File(filePath) {
15
+ return new Promise((resolve, reject) => {
16
+ const hash = crypto_1.default.createHash('md5');
17
+ const stream = fs_1.default.createReadStream(filePath);
18
+ stream.on('data', chunk => hash.update(chunk));
19
+ stream.on('error', reject);
20
+ stream.on('end', () => resolve(hash.digest('hex')));
21
+ });
22
+ }
23
+ /**
24
+ * 将目录上传文件拆分为资源组和入口组,确保入口文件最后上传
25
+ */
26
+ function splitEntryUploadFiles(files, entryFiles) {
27
+ // 是否有自定义入口文件
28
+ const hasCustomEntryFiles = Array.isArray(entryFiles);
29
+ // 规范化入口文件路径,去除前导斜线
30
+ const normalizedEntryFiles = (entryFiles || [])
31
+ .map(item => String(item || '').trim().replace(/\\/g, '/').replace(/^\/+/, ''))
32
+ .filter(Boolean);
33
+ const resourceFiles = [];
34
+ const entryUploadFiles = [];
35
+ files.forEach(file => {
36
+ const normalizedCloudPath = file.cloudPath.replace(/\\/g, '/').replace(/^\/+/, '');
37
+ // 判断当前文件是否为入口文件
38
+ const isEntryFile = hasCustomEntryFiles
39
+ ? normalizedEntryFiles.some(entryFile => normalizedCloudPath === entryFile ||
40
+ normalizedCloudPath.endsWith(`/${entryFile}`))
41
+ : path_1.default.posix.basename(normalizedCloudPath) === 'index.html';
42
+ if (isEntryFile) {
43
+ entryUploadFiles.push(file);
44
+ return;
45
+ }
46
+ resourceFiles.push(file);
47
+ });
48
+ return {
49
+ resourceFiles,
50
+ entryUploadFiles
51
+ };
52
+ }