@cloudbase/manager-node 5.9.4 → 5.10.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.
@@ -1,32 +1,162 @@
1
1
  import { Environment } from '../environment';
2
- /** app 声明式配置(cloudbaserc.json app 对象) */
2
+ /**
3
+ * 判断目录下是否存在至少一个**真实文件**(递归)。
4
+ *
5
+ * 忽略 `.DS_Store`:只有该文件的目录在 macOS 上很常见,
6
+ * 若按「非空」通过,会静默发布一个空站点。
7
+ *
8
+ * 必须递归:只看顶层条目名时,「仅有空子目录」(如 `dist/assets/` 为空目录)
9
+ * 会被误判为有产物,于是把空站点当有效产物发布出去。
10
+ * 不跟随软链(`dirent.isDirectory()` 对符号链接为 false),避免环状链接无限递归。
11
+ */
12
+ export declare function hasFilesInDir(dir: string): boolean;
13
+ /**
14
+ * 把用户配置的 `ignore` 归一成字符串数组(app / hosting / uploadCode 三处共用)。
15
+ *
16
+ * 必须与 `uploadFiles` 一样接受 `string | string[]`:cloudbaserc 的 app / hosting
17
+ * 配置是原文透传给部署链路的(中间没有 schema 校验),用户按 `uploadFiles` 的写法
18
+ * 写 `"ignore": "*.map"` 是合法的。而拼接只认数组 —— 直接 `...'*.map'` 会按字符
19
+ * 展开成 `['*', '.', 'm', 'a', 'p']`:用户规则失效,且这些单字符 glob 会误伤大量
20
+ * 产物文件(文件名含 a / m / p 就被排除),站点缺文件、线上 404,全程无报错。
21
+ *
22
+ * 与 `src/deploy/function/config-guard.ts` 的 `Array.isArray` 归一化同一口径。
23
+ *
24
+ * - `undefined` / `null` → `[]`(未配置,只用默认清单)
25
+ * - 字符串 → 单元素数组
26
+ * - 数组 → 原样(逐项校验)
27
+ * - 空串项丢弃:不是合法 glob,留着只会让匹配行为不可预期
28
+ * - 非字符串项 → `INVALID_PARAM`,报错里带字段名
29
+ */
30
+ export declare function normalizeIgnore(ignore: unknown, field: string, name?: string): string[];
31
+ /**
32
+ * `normalizeDeployPath` 的只读版本:非法值返回 `undefined` 而不抛错。
33
+ *
34
+ * 导出给 `DeployOrchestrator.buildAppPlan` 复用:plan 必须与 apply 走**同一个**
35
+ * 校验函数,否则「用户显式配了非法 deployPath」这种场景会在 plan 里渲染成一条
36
+ * 完全正常的计划项,而 apply 必然抛 `INVALID_PARAM` —— 预演与真实发布口径分叉。
37
+ *
38
+ * plan 是只读预演,报错留给 apply 的参数校验,这里只降级为「无规范化值」。
39
+ */
40
+ export declare function tryNormalizeDeployPath(value: string, field: string, mustBeAbsolute?: boolean): string | undefined;
41
+ /**
42
+ * 解析路径并要求落在 `baseDir` 内,返回解析后的绝对路径。
43
+ *
44
+ * 防的是 `outputDir: '../..'` 或绝对路径把项目外文件递归上传并发布成站点。
45
+ * 这里只做字面路径判断;软链逃逸(`ln -s ~/.ssh dist`)需要调用方按需补充
46
+ * (CLI 侧 `safeResolveProjectPath` 有完整实现)。
47
+ *
48
+ * ⚠️ `path.isAbsolute(relative)` 不能省:`path.relative` 在找不到相对路径时
49
+ * 会返回 target 的绝对路径(Windows 跨盘符即如此),只判 `startsWith('..')` 会放行。
50
+ *
51
+ * 类型校验下沉到这里,而不是放在每个调用点:
52
+ * `app.root` / `app.outputDir` / `hosting.root` / `hosting.outputDir` 四个入口都来自
53
+ * 用户手改的 cloudbaserc 原文(无 schema 兜底),`"root": 123` 这类 JSON 合法值会在
54
+ * `path.resolve` 处抛 Node 原生 `ERR_INVALID_ARG_TYPE`,错误里不含任何字段名,用户无从定位。
55
+ * 逐个调用点补校验必然漏(本函数的四个调用点此前就只有一个做了),所以在唯一的收口处拦。
56
+ * 含 NUL 的字符串同理:能过 `path.resolve`,却在 `fs` 调用处抛 `ERR_INVALID_ARG_VALUE`。
57
+ *
58
+ * 导出给 `DeployOrchestrator.resolveBuildHint` 复用:plan 必须与 apply 用**同一个**
59
+ * 校验函数,否则 plan 会在越界路径上报 `artifactReady: true`,而 apply 必然拒绝。
60
+ */
61
+ export declare function resolveInsideBase(baseDir: string, target: string, field: string): string;
62
+ /**
63
+ * 在字面路径校验之上,再按 realpath 校验一次,挡住软链逃逸。
64
+ *
65
+ * 场景:`ln -s ~/.ssh dist` —— `resolveInsideBase` 只看字面路径,会认为 `dist`
66
+ * 就在项目内;实际读取时落在项目外,产物(或私钥)会被发布到公开可访问的托管桶。
67
+ *
68
+ * 目标不存在时 `realpathSync` 抛错,此时不做判断:交给调用方后续的存在性/非空校验
69
+ * 给出更准确的错误(例如 `BUILD_OUTPUT_NOT_FOUND`)。
70
+ *
71
+ * 只做「是否越界」的判定,返回值仍用字面解析结果 —— 避免把 `/var` → `/private/var`
72
+ * 这类系统级软链展开后泄漏到对外可见的路径与日志里。
73
+ *
74
+ * 与 `resolveInsideBase` 一同导出给 `DeployOrchestrator.resolveBuildHint` 复用。
75
+ */
76
+ export declare function assertRealPathInsideBase(options: {
77
+ /** 基准目录(项目根) */
78
+ baseDir: string;
79
+ /** `resolveInsideBase` 返回的字面解析结果 */
80
+ resolved: string;
81
+ /** 配置字段名,用于错误文案 */
82
+ field: string;
83
+ /** 用户配置的原值,用于错误文案 */
84
+ rawTarget: string;
85
+ }): void;
86
+ /**
87
+ * 解析 `app.root` / `hosting.root`:落在 `cwd` 内,且软链解析后仍在 `cwd` 内。
88
+ *
89
+ * 必须用 `||` 而非 `??`:`root: 0 / false / ''` 一律回落 `'.'`。
90
+ * 导出给 `DeployOrchestrator` 复用,plan 与 apply 用同一个函数,不会再出现口径分叉。
91
+ */
92
+ export declare function resolveDeployRoot(cwd: string, rawRoot: unknown, field: string): string;
93
+ /**
94
+ * 解析产物目录(绝对路径),**app 与 hosting 同一套规则**:
95
+ *
96
+ * | `outputDir` | 结果 |
97
+ * |---|---|
98
+ * | 配了(trim 后非空字符串,含 `'.'`) | 按用户配置(用 trim 后的值),不参与推断 |
99
+ * | 没配(`undefined` / `null` / `''` / 纯空白串) | `resolveHostingOutputDir` 推断:显式 buildCommand → `dist`;framework / package.json → 框架默认产物目录;纯静态 → root |
100
+ * | 非字符串 | `INVALID_PARAM`(否则会在 `path.resolve` 处以裸 TypeError 失败) |
101
+ *
102
+ * 推断规则与 `tcb app build` 的产物落点一致:构建到哪里,就从哪里上传。
103
+ * 只解析和做越界 / 软链校验,**不判非空** —— apply 据此抛 `BUILD_OUTPUT_NOT_FOUND`,
104
+ * plan(`DeployOrchestrator`)据此报 `artifactReady`,两边共用本函数。
105
+ */
106
+ export declare function resolveArtifactDir(options: {
107
+ config: {
108
+ outputDir?: unknown;
109
+ framework?: string;
110
+ buildCommand?: string;
111
+ };
112
+ /** 已过 `resolveDeployRoot` 的资源根目录 */
113
+ root: string;
114
+ kind: 'app' | 'hosting';
115
+ /** 资源名(serviceName / hosting name),仅用于错误文案 */
116
+ name?: string;
117
+ }): string;
118
+ /**
119
+ * app 声明式配置(cloudbaserc.json app 对象)
120
+ *
121
+ * `installCommand` / `buildCommand` / `framework` 与 hosting 一样**不会被执行**,
122
+ * 只参与产物目录推断(见 `resolveArtifactDir`)。
123
+ */
3
124
  export interface IAppDeployConfig {
4
125
  serviceName?: string;
5
126
  root?: string;
6
127
  framework?: string;
7
128
  installCommand?: string;
8
129
  buildCommand?: string;
130
+ /** 构建产物目录(相对 root):配了按配置;没配(含 `''`)按框架推断,纯静态回退 root。部署项目根请显式写 `'.'` */
9
131
  outputDir?: string;
10
132
  deployPath?: string;
11
- ignore?: string[];
133
+ /** 排除规则:与 uploadFiles 一致支持单个 glob 字符串或字符串数组(见 normalizeIgnore) */
134
+ ignore?: string | string[];
12
135
  envVariables?: Record<string, string | number | boolean>;
13
136
  }
14
- /** hosting 声明式配置(cloudbaserc.json hosting[]) */
137
+ /**
138
+ * hosting 声明式配置(cloudbaserc.json hosting[])
139
+ *
140
+ * ⚠️ `installCommand` / `buildCommand` / `framework` **不会被执行**:
141
+ * 声明式部署只部署不构建,这三个字段只参与「产物目录推断」
142
+ * (见 framework.resolveHostingOutputDir)。构建请用 `tcb app build` 或自行执行。
143
+ */
15
144
  export interface IHostingDeployConfig {
16
145
  name?: string;
17
146
  root?: string;
18
- /** 框架类型:显式指定或未配置时读 root/package.json 自动检测;static/custom 表示纯静态(不构建) */
147
+ /** 框架类型:显式指定或未配置时读 root/package.json 自动检测;只用于推断产物目录,不触发构建 */
19
148
  framework?: string;
20
- /** 安装命令,默认 npm install;空字符串跳过安装 */
149
+ /** 安装命令:**不执行**,保留以兼容既有配置 */
21
150
  installCommand?: string;
22
- /** 构建命令:非空则本地构建后上传;空字符串/未配置且无法检测 → 纯静态直接上传 outputDir */
151
+ /** 构建命令:**不执行**,仅用于区分「有构建场景(产物默认 dist)」与「纯静态(产物默认 root)」 */
23
152
  buildCommand?: string;
24
- /** 构建产物目录:有构建时默认 dist,纯静态时默认 root */
153
+ /** 构建产物目录:有构建配置时默认 dist,纯静态时默认 root。目录必须已存在且非空 */
25
154
  outputDir?: string;
26
155
  /** 云端部署路径(决定访问 URL 与网关 PathRewrite.Prefix) */
27
156
  deployPath?: string;
28
- ignore?: string[];
29
- /** 构建时环境变量(注入本地构建进程,非敏感) */
157
+ /** 排除规则:与 uploadFiles 一致支持单个 glob 字符串或字符串数组(见 normalizeIgnore) */
158
+ ignore?: string | string[];
159
+ /** 构建时环境变量:本层不再执行构建,故**不生效**;`tcb app build` 会使用它 */
30
160
  envVariables?: Record<string, string | number | boolean>;
31
161
  /**
32
162
  * 多页应用(MPA)入口文件列表,相对于产物目录,默认 ["index.html"]。
@@ -47,66 +177,100 @@ export interface IStaticDeployResult {
47
177
  wroteRecord: boolean;
48
178
  }
49
179
  /**
50
- * app/hosting 声明式部署器
180
+ * app/hosting 声明式部署器 —— **只部署,不构建**
51
181
  *
52
- * app:framework=static → 直传产物 + SkipBuild 写记录(对齐 tcb app deploy 纯静态分支);
53
- * 其余 framework → 云端构建(上传源码 → 云端构建 → 写版本记录),与现有 tcb app deploy 一致
54
- * hosting:固定静态流程(buildCommand 非空则本地构建后直传),不写版本记录(现有 tcb hosting deploy 行为)
182
+ * 声明式部署(CLI `tcb deploy` / MCP `deployApply`)的定位是「只部署」。构建由用户
183
+ * 自己完成,或走 `tcb app build`(本地)/ `tcb app deploy`(云端,不经过本类)。
184
+ * 本类不再执行任何构建命令,产物缺失即抛 `BUILD_OUTPUT_NOT_FOUND`。
185
+ *
186
+ * - app:产物直传 + `createApp(SkipBuild)` 写部署记录
187
+ * - hosting:产物直传,不写版本记录(保持 `tcb hosting deploy` 的既有行为)
188
+ *
189
+ * 两者的产物目录解析、就绪校验、上传排除清单完全一致(`resolveArtifactDir` /
190
+ * `assertArtifactReady` / `uploadArtifact`)。`buildCommand` / `framework` 仍被读取,
191
+ * 但只用于**推断产物目录**,不再执行;写部署记录时 `framework` 固定下发 `'static'`
192
+ * (跳过构建的唯一认可值,见 `SKIP_BUILD_FRAMEWORK`)。
55
193
  */
56
194
  export declare class StaticDeployer {
57
195
  private environment;
58
196
  constructor(environment: Environment);
59
197
  /**
60
- * app 部署(与现有 tcb app deploy 一致)
198
+ * app 部署:**只部署,不构建**。
199
+ *
200
+ * 无条件走「产物直传 + `createApp({ skipBuild: true })`」写部署记录,
201
+ * 不再根据 `framework` 分叉到云端构建。理由:声明式部署(`tcb deploy`)
202
+ * 的定位是只部署,构建由用户用 `tcb app build`(本地)或
203
+ * CLI 的 `tcb app deploy`(云端,不经过本方法)完成。
61
204
  *
62
- * framework=static:直传产物(hosting uploadFiles)+ createApp(SkipBuild) 后台写部署记录,跳过云端构建。
63
- * 其余 framework:上传源码 ZIP → createApp 云端构建 → 写版本记录。
205
+ * 产物目录与 hosting 同一套规则(见 `resolveArtifactDir`):配了按配置,没配按
206
+ * buildCommand / framework / package.json 推断,纯静态回退 `app.root`。
207
+ *
208
+ * @throws CloudBaseError `INVALID_PARAM` 缺 serviceName / 路径越界 / outputDir 类型非法
209
+ * @throws CloudBaseError `BUILD_OUTPUT_NOT_FOUND` 产物目录不存在或为空
64
210
  */
65
211
  deployApp(options: {
66
212
  config: IAppDeployConfig;
67
213
  cwd?: string;
68
214
  }): Promise<IStaticDeployResult>;
69
215
  /**
70
- * hosting 部署(固定静态流程,不写版本记录)
216
+ * hosting 部署:**只部署,不构建**(不写版本记录)
217
+ *
218
+ * 与 `deployApp` 同一口径:声明式部署(`tcb deploy` / MCP `deployApply`)的定位是
219
+ * 「只部署」,构建由用户自己完成或走 `tcb app build`(本地)。
220
+ *
221
+ * 为什么构建必须从这里移除、而不是只在 CLI 侧中立化:
222
+ * CLI 的 `neutralizeHostingForDeploy` 会清空 `buildCommand` 后再调用本方法,
223
+ * 因此从 CLI 进来看不出差别;但 MCP 的 `deployApply` 直接读 cloudbaserc 调用本方法,
224
+ * 不经过中立化 ⇒ 若构建留在这里,同一份 cloudbaserc 会出现
225
+ * 「CLI 不构建、MCP 构建」的行为分叉,且 `app` 已经不构建,
226
+ * 变成「app 不构建、hosting 构建」的半截状态。单一真相源只能放在本层。
227
+ *
228
+ * `buildCommand` / `installCommand` 仍被接收但**不再执行**:它们现在只是
229
+ * 「产物目录推断」的输入(见 `resolveArtifactDir`),配置无需改写即可平滑过渡。
71
230
  *
72
- * 支持本地构建:buildCommand 非空时自动执行 build 后上传产物(依赖由用户自行安装,
73
- * 不代为执行 npm install);
74
- * 纯静态(buildCommand 空/未配置且无法检测框架)时直接上传 outputDir(默认 root,保持现状)。
75
231
  * 访问地址 = https://{CdnDomain}{deployPath}(与 tcb hosting deploy 一致)
232
+ *
233
+ * @throws CloudBaseError `INVALID_PARAM` 路径越界 / outputDir 类型非法
234
+ * @throws CloudBaseError `BUILD_OUTPUT_NOT_FOUND` 产物目录不存在或为空
76
235
  */
77
236
  deployHosting(options: {
78
237
  config: IHostingDeployConfig;
79
238
  cwd?: string;
80
239
  }): Promise<IStaticDeployResult>;
240
+ /**
241
+ * 产物直传静态托管(app / hosting 共用)。
242
+ *
243
+ * `userIgnore` 必须由调用方在入口用 `normalizeIgnore` 归一后传入:
244
+ * 归一化只做一次,避免「同一个 config.ignore 在两条路径上各归一一次」——
245
+ * 只要有一处被改回直接 spread 原始值,字符串 `'*.map'` 就会按字符展开成
246
+ * `['*','.','m','a','p']`,误杀大量产物且不报错。
247
+ */
248
+ private uploadArtifact;
81
249
  /**
82
250
  * app 纯静态直传(对齐 tcb app deploy 的 deployStaticApp 分支)
83
251
  *
84
252
  * 1. hosting uploadFiles 直传产物(文件级上传,立即可访问,无需打 ZIP)
85
- * 2. 后台异步 createApp(SkipBuild) 写部署记录(失败不影响文件访问)
253
+ * 2. createApp(SkipBuild) 写部署记录(失败时抛错,但说明产物已可访问)
86
254
  * 3. 跳过云端构建轮询,返回访问地址
255
+ *
256
+ * 调用前产物目录必须已解析并校验就绪(见 `deployApp`)。
87
257
  */
88
258
  private deployAppStatic;
89
- /**
90
- * app 云端构建:上传源码 ZIP → createApp 云端构建 → 写版本记录
91
- */
92
- private deployAppCloud;
93
259
  /**
94
260
  * 解析 hosting 访问地址:https://{CdnDomain}{deployPath}
95
261
  */
96
262
  private resolveHostingUrl;
97
263
  /**
98
- * 本地构建(仅执行 buildCommand,不安装依赖)
264
+ * 解析 app 访问地址(DescribeCloudAppInfo.Domain 为准,托管 CDN 仅兜底)
99
265
  *
100
- * 只跑用户的构建命令,依赖由用户自行安装(对齐业界:Vercel/Netlify/Cloudflare
101
- * 均不在本地构建时代装依赖)。installCommand 不再被本地执行 —— CLI 侧通过
102
- * installCommand: '' 已可跳过云端安装;本地一律不装。
266
+ * 拼接规则与 CLI `lib/app/utils.js` 的 `buildAppUrl` 同口径:
103
267
  *
104
- * - buildCommand:由调用方保证非空(hosting 经 resolveBuildCommand 判定;app local 由 if 判定)
105
- * - envVariables:注入构建进程环境变量(值统一转字符串)
106
- */
107
- private runLocalBuild;
108
- /**
109
- * 解析 app 访问地址(describeAppInfo.Domain + appPath)
268
+ * - **独立域名**(不含 `tcloudbaseapp.com`,如 `*.webapps.tcloudbase.com` / 自定义域名):
269
+ * 域名本身已定位到应用,**不拼路径**,返回 `https://{domain}/`。
270
+ * 控制台「访问域名」展示的就是裸域名,拼上 AppPath 反而 404
271
+ * (AppPath 是托管桶内的目录,不是该域名下的 URL 路径)。
272
+ * - **环境级共享域名**(`*.tcloudbaseapp.com`):桶被整个环境共用,必须拼路径定位应用,
273
+ * 优先用服务端返回的 `AppPath`(用户可能在控制台改过),本地 `appPath` 仅作 fallback。
110
274
  */
111
275
  private resolveAppUrl;
112
276
  }
@@ -64,9 +64,10 @@ export declare function resolveHostingOutputDir(config: IHostingOutputConfig, ro
64
64
  /**
65
65
  * 本地构建单个 hosting 项(仅执行 buildCommand,不安装依赖,不上传)
66
66
  *
67
- * 从 StaticDeployer.runLocalBuild 提炼的纯函数版:不依赖 Environment,
68
- * 供 CLI 的 tcb app build 与任何需要「只构建不上传」的调用方复用,
69
- * 避免各端各自复制推断/执行逻辑。buildCommand 为空 → 直接返回 null。
67
+ * 从原 StaticDeployer.runLocalBuild 提炼的纯函数版(该方法已随「声明式部署只部署
68
+ * 不构建」一并移除,构建入口只剩这里):不依赖 Environment,供 CLI 的 tcb app build
69
+ * 与任何需要「只构建不上传」的调用方复用,避免各端各自复制推断/执行逻辑。
70
+ * buildCommand 为空 → 直接返回 null。
70
71
  *
71
72
  * @param config hosting 项配置(framework/buildCommand/outputDir,root 单独传参)
72
73
  * @param root 项目目录(绝对路径)
@@ -27,6 +27,15 @@ export declare const ERROR_TYPES: {
27
27
  readonly fileError: {
28
28
  readonly code: "FILE_READ_ERROR";
29
29
  };
30
+ /**
31
+ * 部署前未找到构建产物(目录不存在或为空)。
32
+ *
33
+ * 声明式部署(`tcb deploy`)不执行构建,产物必须由用户先产出;
34
+ * 这个码让 CLI 侧能稳定映射到非零退出码并给出「先构建」的引导。
35
+ */
36
+ readonly buildOutputNotFound: {
37
+ readonly code: "BUILD_OUTPUT_NOT_FOUND";
38
+ };
30
39
  };
31
40
  export type ErrorTypeName = keyof typeof ERROR_TYPES;
32
41
  export type ErrorType = (typeof ERROR_TYPES)[ErrorTypeName];
@@ -1,5 +1,5 @@
1
1
  import { Environment } from '../environment';
2
- import { CreatePlatformEnvParams, CreatePlatformEnvRes, CreatePlatformHTTPServiceRouteParams, CreatePlatformHTTPServiceRouteRes, DescribePlatformAccountCircleParams, DescribePlatformAccountCircleRes, DescribePlatformCreditsUsageDetailParams, DescribePlatformCreditsUsageDetailRes, DescribePlatformCreditsUsageParams, DescribePlatformCreditsUsageRes, DescribePlatformEnvCreditsRankingParams, DescribePlatformEnvCreditsRankingRes, DescribePlatformEnvUsageParams, DescribePlatformEnvUsageRes, DescribePlatformHTTPServiceRouteParams, DescribePlatformHTTPServiceRouteRes, DescribePlatformPackageListParams, DescribePlatformPackageListRes, DescribePlatformsParams, DescribePlatformsRes, DeletePlatformHTTPServiceRouteParams, DeletePlatformHTTPServiceRouteRes, DestroyPlatformEnvParams, DestroyPlatformEnvRes, ModifyPlatformEnvParams, ModifyPlatformEnvRes, ModifyPlatformHTTPServiceRouteParams, ModifyPlatformHTTPServiceRouteRes, VerifyPlatformHTTPServiceRouteParams, VerifyPlatformHTTPServiceRouteRes } from './type';
2
+ import { CreateHttpServiceErrorPageParams, CreateHttpServiceErrorPageRes, CreatePlatformEnvParams, CreatePlatformEnvRes, CreatePlatformHTTPServiceRouteParams, CreatePlatformHTTPServiceRouteRes, DescribeHttpServiceErrorPageParams, DescribeHttpServiceErrorPageRes, DescribePlatformAccountCircleParams, DescribePlatformAccountCircleRes, DescribePlatformCreditsUsageDetailParams, DescribePlatformCreditsUsageDetailRes, DescribePlatformCreditsUsageParams, DescribePlatformCreditsUsageRes, DescribePlatformEnvCreditsRankingParams, DescribePlatformEnvCreditsRankingRes, DescribePlatformEnvUsageParams, DescribePlatformEnvUsageRes, DescribePlatformHTTPServiceRouteParams, DescribePlatformHTTPServiceRouteRes, DescribePlatformPackageListParams, DescribePlatformPackageListRes, DescribePlatformsParams, DescribePlatformsRes, DeleteHttpServiceErrorPageParams, DeleteHttpServiceErrorPageRes, DeletePlatformHTTPServiceRouteParams, DeletePlatformHTTPServiceRouteRes, DestroyPlatformEnvParams, DestroyPlatformEnvRes, ModifyHttpServiceErrorPageParams, ModifyHttpServiceErrorPageRes, ModifyPlatformEnvParams, ModifyPlatformEnvRes, ModifyPlatformHTTPServiceRouteParams, ModifyPlatformHTTPServiceRouteRes, VerifyPlatformHTTPServiceRouteParams, VerifyPlatformHTTPServiceRouteRes } from './type';
3
3
  /**
4
4
  * 平台版服务
5
5
  * 提供平台版套餐查询、资源用量统计、环境生命周期管理及 HTTP 访问服务路由管理能力
@@ -130,4 +130,57 @@ export declare class PlatformService {
130
130
  * @returns {Promise<DescribePlatformHTTPServiceRouteRes>} 域名路由列表及域名总数
131
131
  */
132
132
  describePlatformHttpServiceRoute(params: DescribePlatformHTTPServiceRouteParams): Promise<DescribePlatformHTTPServiceRouteRes>;
133
+ /**
134
+ * 上传本地错误页文件并创建 HTTP 访问服务自定义错误页配置
135
+ * 文件上传至平台静态托管桶根目录 error-pages/{PlatformId}/{文件名},不拼接 BasePath。
136
+ * 文件名中的空白和括号替换为 -;同名文件会被覆盖。
137
+ * ResourceType 固定为 STATIC_STORE,ResourceName 固定为 staticstore,RewritePath 自动生成。
138
+ * 支持一次为多个状态码绑定同一个错误页;同一状态码只允许一个配置,创建前会先查重,
139
+ * 命中已有配置时直接报错且不上传文件。
140
+ * 上传失败时不创建规则;创建失败时保留已上传文件,不自动删除或回滚覆盖的对象。
141
+ * @param {CreateHttpServiceErrorPageParams} params 平台版 ID、状态码列表和本地文件路径
142
+ * @returns {Promise<CreateHttpServiceErrorPageRes>} 创建成功个数
143
+ */
144
+ createHttpServiceErrorPage(params: CreateHttpServiceErrorPageParams): Promise<CreateHttpServiceErrorPageRes>;
145
+ /**
146
+ * 更新 HTTP 访问服务自定义错误页配置
147
+ * 与 ModifyHTTPServiceErrorPage 的入参保持一致:按 Id 更新一条配置,HttpStatusCode 为修改后的完整集合。
148
+ * 传入 localPath 时上传新文件并以 error-pages/{PlatformId}/{文件名} 作为 RewritePath;
149
+ * 不传 localPath 时沿用该记录现有文件,仅更新状态码等配置。
150
+ * 一条记录只对应一份错误页文件,换文件会作用于该记录绑定的全部状态码。
151
+ * 上传失败时不更新规则;更新失败时保留已上传文件,不自动删除或回滚覆盖的对象。
152
+ * @param {ModifyHttpServiceErrorPageParams} params 平台版 ID、配置 ID、状态码集合与可选的本地文件路径
153
+ * @returns {Promise<ModifyHttpServiceErrorPageRes>} 更新成功个数
154
+ */
155
+ modifyHttpServiceErrorPage(params: ModifyHttpServiceErrorPageParams): Promise<ModifyHttpServiceErrorPageRes>;
156
+ /**
157
+ * 删除 HTTP 访问服务自定义错误页配置
158
+ * 直接按 Id 整条删除;一条记录可能同时绑定多个状态码(共用同一份静态资源与 Id),
159
+ * 删除会一并移除这些状态码的映射。
160
+ * 删除成功后异步清理对应的 COS 文件,清理失败不影响删除结果;
161
+ * 该文件仍被其他配置引用时不会删除。
162
+ * @param {DeleteHttpServiceErrorPageParams} params 平台版 ID 与配置 ID
163
+ * @returns {Promise<DeleteHttpServiceErrorPageRes>} 删除成功个数
164
+ */
165
+ deleteHttpServiceErrorPage(params: DeleteHttpServiceErrorPageParams): Promise<DeleteHttpServiceErrorPageRes>;
166
+ /**
167
+ * 查询 HTTP 访问服务自定义错误页配置列表
168
+ * 平台版能力,通过 PlatformId 指定平台。
169
+ * 按 HTTP 状态码数组查询已配置的错误页,如 ['404', '403'];不传状态码时返回该平台全部配置。
170
+ * @param {DescribeHttpServiceErrorPageParams} params 查询参数,包含平台版 ID 及可选的 HTTP 状态码
171
+ * @returns {Promise<DescribeHttpServiceErrorPageRes>} 错误页配置列表及总条数
172
+ */
173
+ describeHttpServiceErrorPage(params: DescribeHttpServiceErrorPageParams): Promise<DescribeHttpServiceErrorPageRes>;
174
+ /**
175
+ * 解析平台静态托管桶与地域
176
+ * 取自 DescribePlatforms 返回的 hosting 资源 Detail,是所有上传与清理操作的前提
177
+ */
178
+ private resolveErrorPageHostingBucket;
179
+ /** 校验本地文件并上传至桶根目录 error-pages/{PlatformId}/{文件名},返回 RewritePath */
180
+ private uploadErrorPageFile;
181
+ /**
182
+ * 静默清理错误页文件:仅允许 error-pages/{PlatformId}/ 前缀;
183
+ * 清理前确认没有其他配置继续引用该文件,避免误删共用文件或刚上传的新文件;失败不影响主流程
184
+ */
185
+ private cleanupErrorPageFile;
133
186
  }
@@ -523,3 +523,121 @@ export interface DescribePlatformHTTPServiceRouteRes {
523
523
  /** 唯一请求 ID */
524
524
  RequestId: string;
525
525
  }
526
+ /**
527
+ * 网关客户自定义错误页配置
528
+ */
529
+ export interface GWErrorPageConfig {
530
+ /** 平台版 ID */
531
+ PlatformId?: string;
532
+ /** HTTP 状态码列表,如 ['404', '403'] */
533
+ HttpStatusCode: string[];
534
+ /** 资源类型,当前仅支持静态托管 */
535
+ ResourceType?: 'STATIC_STORE';
536
+ /** 资源名称 */
537
+ ResourceName?: string;
538
+ /** 重定向的路径,格式为 /error-pages/{$platformId}/xxx,xxx 为具体文件名(含后缀) */
539
+ RewritePath?: string;
540
+ }
541
+ /**
542
+ * 上传本地错误页文件并创建 HTTP 访问服务错误页配置
543
+ */
544
+ export interface CreateHttpServiceErrorPageParams {
545
+ /** 平台版 ID */
546
+ PlatformId: string;
547
+ /** HTTP 状态码列表,如 ['404', '403'];支持多个状态码绑定同一个错误页 */
548
+ HttpStatusCode: string[];
549
+ /** 本地错误页文件路径;上传至桶根目录 error-pages/{PlatformId}/{文件名},同名文件会被覆盖 */
550
+ localPath: string;
551
+ }
552
+ /**
553
+ * CreateHTTPServiceErrorPage 返回结果
554
+ */
555
+ export interface CreateHttpServiceErrorPageRes {
556
+ /** 创建成功个数 */
557
+ Count: number;
558
+ /** 唯一请求 ID */
559
+ RequestId?: string;
560
+ }
561
+ /**
562
+ * 更新 HTTP 访问服务错误页配置
563
+ */
564
+ export interface ModifyHttpServiceErrorPageParams {
565
+ /** 平台版 ID */
566
+ PlatformId: string;
567
+ /** 配置 ID,来自 describeHttpServiceErrorPage 返回的 Configs[].Id */
568
+ Id: number;
569
+ /** 修改后的完整状态码集合,如 ['403', '404'] */
570
+ HttpStatusCode: string[];
571
+ /** 新的本地错误页文件路径;不传时沿用该记录现有的文件 */
572
+ localPath?: string;
573
+ }
574
+ /**
575
+ * ModifyHTTPServiceErrorPage 返回结果
576
+ */
577
+ export interface ModifyHttpServiceErrorPageRes {
578
+ /** 更新成功个数 */
579
+ Count: number;
580
+ /** 唯一请求 ID */
581
+ RequestId?: string;
582
+ }
583
+ /**
584
+ * 删除 HTTP 访问服务错误页配置
585
+ */
586
+ export interface DeleteHttpServiceErrorPageParams {
587
+ /** 平台版 ID */
588
+ PlatformId: string;
589
+ /** 配置 ID,来自 describeHttpServiceErrorPage 返回的 Configs[].Id */
590
+ Id: number;
591
+ }
592
+ /**
593
+ * DeleteHTTPServiceErrorPage 返回结果
594
+ */
595
+ export interface DeleteHttpServiceErrorPageRes {
596
+ /** 删除成功个数 */
597
+ Count: number;
598
+ /** 唯一请求 ID */
599
+ RequestId?: string;
600
+ }
601
+ /**
602
+ * 客户自定义错误页配置列表项
603
+ */
604
+ export interface HTTPServiceErrorPageListItem {
605
+ /** 平台版 ID */
606
+ PlatformId?: string;
607
+ /** HTTP 状态码列表,如 ['404', '403'] */
608
+ HttpStatusCode: string[];
609
+ /** 资源类型,当前仅支持静态托管 */
610
+ ResourceType?: 'STATIC_STORE';
611
+ /** 资源名称 */
612
+ ResourceName?: string;
613
+ /** 重定向的路径,格式为 /error-pages/{$platformId}/xxx,xxx 为具体文件名(含后缀) */
614
+ RewritePath?: string;
615
+ /** 数据库表 id */
616
+ Id?: number;
617
+ /** 状态。0: 正常使用,1: 已删除,通常只返回正常状态的配置 */
618
+ Status?: number;
619
+ /** 创建时间 */
620
+ CreateTime?: string;
621
+ /** 更新时间 */
622
+ UpdateTime?: string;
623
+ }
624
+ /**
625
+ * DescribeHTTPServiceErrorPage 请求参数
626
+ */
627
+ export interface DescribeHttpServiceErrorPageParams {
628
+ /** 平台版 ID */
629
+ PlatformId?: string;
630
+ /** HTTP 状态码列表,如 ['404', '403'];不传时返回该平台全部错误页配置 */
631
+ HttpStatusCode?: string[];
632
+ }
633
+ /**
634
+ * DescribeHTTPServiceErrorPage 返回结果
635
+ */
636
+ export interface DescribeHttpServiceErrorPageRes {
637
+ /** 数量总条数 */
638
+ TotalCount: number;
639
+ /** 客户自定义错误页配置列表 */
640
+ Configs: HTTPServiceErrorPageListItem[];
641
+ /** 唯一请求 ID */
642
+ RequestId?: string;
643
+ }
@@ -0,0 +1,17 @@
1
+ import { Environment } from '../environment';
2
+ interface CosFileUploadOptions {
3
+ bucket: string;
4
+ region: string;
5
+ key: string;
6
+ localPath: string;
7
+ }
8
+ interface CosObjectOptions {
9
+ bucket: string;
10
+ region: string;
11
+ key: string;
12
+ }
13
+ /** 使用当前 SDK 凭证上传单文件,Key 相对于桶根目录,不加载环境信息或拼接 BasePath。 */
14
+ export declare function uploadCosFile(environment: Environment, options: CosFileUploadOptions): Promise<void>;
15
+ /** 删除桶根目录下的单个对象,Key 不做任何路径变换。 */
16
+ export declare function deleteCosObject(environment: Environment, options: CosObjectOptions): Promise<void>;
17
+ export {};
@@ -1,4 +1,59 @@
1
1
  type SizeUnit = 'MB' | 'GB';
2
+ /**
3
+ * 把路径统一成 glob 模式使用的 `/` 分隔形式。
4
+ *
5
+ * micromatch 的 pattern 一律用 `/`(`**\/.env`、`**\/node_modules/**`),而
6
+ * `path.join` 在 Windows 上产出 `sub\dist\.env` ⇒ `isMatch` 全部返回 false。
7
+ * 也就是说:**在 Windows 上 ignore 清单会整份失效**。
8
+ *
9
+ * 这不是理论问题:静态托管的敏感文件排除(`.git` / `.env` / 私钥)就完全依赖
10
+ * `micromatch.isMatch` 的结果,`outputDir: '.'` 时整份提交历史与密钥会被发布到
11
+ * 公开可访问的托管桶。
12
+ *
13
+ * 用 `replace(/\\/g, '/')` 而不是 `split(path.sep).join('/')`:后者在 POSIX 上
14
+ * 不会转换反斜杠,跨平台测试无法覆盖 Windows 分支(回归会重新漏掉)。
15
+ */
16
+ export declare function toPosixPath(filePath: string): string;
17
+ /**
18
+ * 判断本地文件路径是否被 ignore 清单命中。
19
+ *
20
+ * ignore 是「相对于业务根目录」的 glob 语义(见 `utils/ignore.ts` 的
21
+ * DEFAULT_ARTIFACT_IGNORE),而上传入口拿到的 `filePath` 常常是 `path.resolve()`
22
+ * 后的绝对路径(hosting 单文件分支塞进 `files[].localPath` 的就是这种)。
23
+ * micromatch 不会把 `/proj/dist/node_modules/x.js` 与 `node_modules/**` 匹配上,
24
+ * 只做 `toPosixPath` 只统一了分隔符、没统一「基准」⇒ 根锚定 pattern 静默失效。
25
+ *
26
+ * 对齐办法由调用方显式提供 `relativePath`(文件相对于 ignore 根目录的路径,
27
+ * 上传场景就是 `cloudPath`):
28
+ * - 绝对路径本身参与匹配 ⇒ `**\/` 前缀的 pattern 正常命中;
29
+ * - `relativePath` 参与匹配 ⇒ 根锚定 pattern 按「业务根目录」语义命中。
30
+ *
31
+ * ⚠️ 绝不通过「逐段剥离绝对路径」去猜根目录:那会把用户想表达的根锚定 pattern
32
+ * 静默放大成任意层级匹配 —— `static/**` 会连 `public/static/logo.png` 一起排除,
33
+ * 产物缺文件、线上 404 且无任何告警(stbug-51EX9nJY4f)。
34
+ * 宁可让根锚定 pattern 在拿不到 `relativePath` 时不命中(保守放行),
35
+ * 也不能让它命中不该命中的文件(静默破坏产物)。
36
+ *
37
+ * ⚠️ 与 walkLocalDir 的口径一致:两者最终都是拿「相对路径」去匹配,
38
+ * 差别只在 walkLocalDir 自己算相对路径,这里由调用方传进来。
39
+ */
40
+ export declare function isIgnoredPath(filePath: string, ignore?: string | string[], relativePath?: string): boolean;
41
+ /**
42
+ * 统一的 ignore 匹配入口(`isIgnoredPath` 与 `walkLocalDir` 共用)。
43
+ *
44
+ * `dot: true` 是必需的,不是为了放宽用户规则,而是为了堵住一个静默失效:
45
+ * micromatch 默认 `dot: false`,`**` / `*` **不会穿越以点开头的目录**。
46
+ * 于是 `**\/id_rsa*` 打不到 `.ssh/id_rsa`、`**\/*.pem` 打不到 `.ssh/key.pem`、
47
+ * `**\/*.key` 打不到 `.gnupg/*.key` —— 点目录里的私钥整体逃过排除,
48
+ * 而项目根存在 `.ssh/` 在本地开发机上极其常见(stbug-KlBy1JWhvD)。
49
+ *
50
+ * 副作用仅限「排除范围变大」:用户写 `*.map` 时 `.foo.map` 也会被排除。
51
+ * 排除语义放大是可以接受的,漏排一个私钥不可接受。
52
+ *
53
+ * ⚠️ `dot: true` 只让通配符能进点目录,**不能**凭空识别 `.npmrc` 这类
54
+ * 仅靠文件名区分的凭证 —— 这类条目必须显式写进清单。
55
+ */
56
+ export declare function matchesIgnorePattern(candidate: string, ignore: string | string[]): boolean;
2
57
  export declare function checkFullAccess(dest: string, throwError?: boolean): boolean;
3
58
  export declare function checkReadable(dest: string, throwError?: boolean): boolean;
4
59
  export declare function isDirectory(dest: string): boolean;