@cloudbase/manager-node 4.2.3 → 4.2.4
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 +4 -0
- package/package.json +4 -3
- package/lib/access/index.js +0 -141
- package/lib/access/types.js +0 -2
- package/lib/billing/index.js +0 -36
- package/lib/cam/index.js +0 -77
- package/lib/cloudBaseRun/index.js +0 -36
- package/lib/cloudBaseRun/types.js +0 -2
- package/lib/common/index.js +0 -39
- package/lib/constant.js +0 -51
- package/lib/context.js +0 -14
- package/lib/database/index.js +0 -244
- package/lib/debug.js +0 -34
- package/lib/env/index.js +0 -488
- package/lib/environment.js +0 -124
- package/lib/environmentManager.js +0 -44
- package/lib/error.js +0 -16
- package/lib/function/index.js +0 -1022
- package/lib/function/packer.js +0 -129
- package/lib/function/types.js +0 -2
- package/lib/hosting/index.js +0 -461
- package/lib/index.js +0 -83
- package/lib/interfaces/base.interface.js +0 -2
- package/lib/interfaces/billing.interface.js +0 -2
- package/lib/interfaces/cam.interface.js +0 -2
- package/lib/interfaces/flexdb.interface.js +0 -2
- package/lib/interfaces/function.interface.js +0 -2
- package/lib/interfaces/index.js +0 -19
- package/lib/interfaces/storage.interface.js +0 -2
- package/lib/interfaces/tcb.interface.js +0 -2
- package/lib/storage/index.js +0 -1037
- package/lib/third/index.js +0 -18
- package/lib/user/index.js +0 -136
- package/lib/user/types.js +0 -2
- package/lib/utils/auth.js +0 -97
- package/lib/utils/cloud-api-request.js +0 -205
- package/lib/utils/cloudbase-request.js +0 -69
- package/lib/utils/envLazy.js +0 -18
- package/lib/utils/fs.js +0 -64
- package/lib/utils/http-request.js +0 -44
- package/lib/utils/index.js +0 -103
- package/lib/utils/parallel.js +0 -69
- package/lib/utils/uuid.js +0 -18
- package/src/access/index.ts +0 -168
- package/src/access/types.ts +0 -55
- package/src/billing/index.ts +0 -43
- package/src/cam/index.ts +0 -106
- package/src/cloudBaseRun/index.ts +0 -40
- package/src/cloudBaseRun/types.ts +0 -24
- package/src/common/index.ts +0 -54
- package/src/constant.ts +0 -56
- package/src/context.ts +0 -18
- package/src/database/index.ts +0 -369
- package/src/debug.ts +0 -34
- package/src/env/index.ts +0 -614
- package/src/environment.ts +0 -156
- package/src/environmentManager.ts +0 -50
- package/src/error.ts +0 -27
- package/src/function/index.ts +0 -1378
- package/src/function/packer.ts +0 -164
- package/src/function/types.ts +0 -165
- package/src/hosting/index.ts +0 -698
- package/src/index.ts +0 -127
- package/src/interfaces/base.interface.ts +0 -8
- package/src/interfaces/billing.interface.ts +0 -21
- package/src/interfaces/cam.interface.ts +0 -28
- package/src/interfaces/flexdb.interface.ts +0 -104
- package/src/interfaces/function.interface.ts +0 -75
- package/src/interfaces/index.ts +0 -7
- package/src/interfaces/storage.interface.ts +0 -29
- package/src/interfaces/tcb.interface.ts +0 -642
- package/src/storage/index.ts +0 -1290
- package/src/third/index.ts +0 -24
- package/src/user/index.ts +0 -174
- package/src/user/types.ts +0 -21
- package/src/utils/auth.ts +0 -112
- package/src/utils/cloud-api-request.ts +0 -252
- package/src/utils/cloudbase-request.ts +0 -109
- package/src/utils/envLazy.ts +0 -15
- package/src/utils/fs.ts +0 -57
- package/src/utils/http-request.ts +0 -37
- package/src/utils/index.ts +0 -103
- package/src/utils/parallel.ts +0 -82
- package/src/utils/uuid.ts +0 -14
- package/types/access/index.d.ts +0 -38
- package/types/access/types.d.ts +0 -42
- package/types/billing/index.d.ts +0 -21
- package/types/cam/index.d.ts +0 -63
- package/types/cloudBaseRun/index.d.ts +0 -12
- package/types/cloudBaseRun/types.d.ts +0 -21
- package/types/common/index.d.ts +0 -18
- package/types/constant.d.ts +0 -37
- package/types/context.d.ts +0 -17
- package/types/database/index.d.ts +0 -66
- package/types/debug.d.ts +0 -1
- package/types/env/index.d.ts +0 -144
- package/types/environment.d.ts +0 -51
- package/types/environmentManager.d.ts +0 -13
- package/types/error.d.ts +0 -18
- package/types/function/index.d.ts +0 -379
- package/types/function/packer.d.ts +0 -37
- package/types/function/types.d.ts +0 -156
- package/types/hosting/index.d.ts +0 -253
- package/types/index.d.ts +0 -52
- package/types/interfaces/base.interface.d.ts +0 -7
- package/types/interfaces/billing.interface.d.ts +0 -18
- package/types/interfaces/cam.interface.d.ts +0 -24
- package/types/interfaces/flexdb.interface.d.ts +0 -67
- package/types/interfaces/function.interface.d.ts +0 -65
- package/types/interfaces/index.d.ts +0 -7
- package/types/interfaces/storage.interface.d.ts +0 -26
- package/types/interfaces/tcb.interface.d.ts +0 -305
- package/types/storage/index.d.ts +0 -324
- package/types/third/index.d.ts +0 -11
- package/types/user/index.d.ts +0 -52
- package/types/user/types.d.ts +0 -20
- package/types/utils/auth.d.ts +0 -8
- package/types/utils/cloud-api-request.d.ts +0 -21
- package/types/utils/cloudbase-request.d.ts +0 -14
- package/types/utils/envLazy.d.ts +0 -1
- package/types/utils/fs.d.ts +0 -7
- package/types/utils/http-request.d.ts +0 -2
- package/types/utils/index.d.ts +0 -20
- package/types/utils/parallel.d.ts +0 -17
- package/types/utils/uuid.d.ts +0 -2
package/src/hosting/index.ts
DELETED
|
@@ -1,698 +0,0 @@
|
|
|
1
|
-
import fs from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import makeDir from 'make-dir'
|
|
4
|
-
import { CloudBaseError } from '../error'
|
|
5
|
-
import { Environment } from '../environment'
|
|
6
|
-
import {
|
|
7
|
-
CloudService,
|
|
8
|
-
preLazy,
|
|
9
|
-
checkReadable,
|
|
10
|
-
isDirectory,
|
|
11
|
-
checkFullAccess,
|
|
12
|
-
fetchStream
|
|
13
|
-
} from '../utils'
|
|
14
|
-
import { IListFileInfo } from '../interfaces'
|
|
15
|
-
import { AsyncTaskParallelController } from '../utils/parallel'
|
|
16
|
-
|
|
17
|
-
const envDomainCache = new Map()
|
|
18
|
-
|
|
19
|
-
export interface IProgressData {
|
|
20
|
-
loaded: number // 已经上传的部分 字节
|
|
21
|
-
total: number // 整个文件的大小 字节
|
|
22
|
-
speed: number // 文件上传速度 字节/秒
|
|
23
|
-
percent: number // 百分比 小数 0 - 1
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export type OnProgress = (progressData: IProgressData) => void
|
|
27
|
-
export type OnFileFinish = (error: Error, res: any, fileData: any) => void
|
|
28
|
-
|
|
29
|
-
export interface IHostingFileOptions {
|
|
30
|
-
localPath: string
|
|
31
|
-
cloudPath?: string
|
|
32
|
-
// 上传文件并发数量
|
|
33
|
-
parallel?: number
|
|
34
|
-
files?: {
|
|
35
|
-
localPath: string
|
|
36
|
-
cloudPath: string
|
|
37
|
-
}[]
|
|
38
|
-
onProgress?: OnProgress
|
|
39
|
-
onFileFinish?: OnFileFinish
|
|
40
|
-
ignore?: string | string[]
|
|
41
|
-
// 重试次数
|
|
42
|
-
retryCount?: number
|
|
43
|
-
// 重试时间间隔(毫秒)
|
|
44
|
-
retryInterval?: number
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface IHostingFilesOptions {
|
|
48
|
-
// 上传文件并发数量
|
|
49
|
-
localPath?: string
|
|
50
|
-
cloudPath?: string
|
|
51
|
-
parallel?: number
|
|
52
|
-
files: {
|
|
53
|
-
localPath: string
|
|
54
|
-
cloudPath: string
|
|
55
|
-
}[]
|
|
56
|
-
onProgress?: OnProgress
|
|
57
|
-
onFileFinish?: OnFileFinish
|
|
58
|
-
ignore?: string | string[]
|
|
59
|
-
// 重试次数
|
|
60
|
-
retryCount?: number
|
|
61
|
-
// 重试时间间隔(毫秒)
|
|
62
|
-
retryInterval?: number
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type IHostingOptions = IHostingFileOptions | IHostingFilesOptions
|
|
66
|
-
|
|
67
|
-
export interface IHostingCloudOptions {
|
|
68
|
-
cloudPath: string
|
|
69
|
-
isDir: boolean
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface IBindDomainOptions {
|
|
73
|
-
domain: string
|
|
74
|
-
certId: string
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ICheckSourceOptions {
|
|
78
|
-
domains: string[]
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface ITcbOrigin {
|
|
82
|
-
Master: string // 主站
|
|
83
|
-
Slave: string // 副站
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export interface IIpFilter {
|
|
87
|
-
Switch: string // IP 黑白名单配置开关
|
|
88
|
-
FilterType?: string // IP 黑白名单类型
|
|
89
|
-
Filters?: string[] // IP 黑白名单列表
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export interface IIpFreqLimit {
|
|
93
|
-
Switch: string // IP 限频配置开关
|
|
94
|
-
Qps?: number // 设置每秒请求数限制
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface ITcbAuthentication {
|
|
98
|
-
Switch: string // on/off 开启或关闭
|
|
99
|
-
SecretKey: string // 用户计算签名的秘钥
|
|
100
|
-
SignParam?: string // url串中签名的字段名
|
|
101
|
-
TimeParam?: string // url串中时间的字段名
|
|
102
|
-
ExpireTime?: string // 开启时必填过期时间
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface ITcbCache {
|
|
106
|
-
RuleType: string // 规则类型
|
|
107
|
-
RuleValue: string // 规则内容
|
|
108
|
-
CacheTtl: number // 缓存时间
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export interface ITcbRefererRule {
|
|
112
|
-
RefererType: string // referer 配置类型
|
|
113
|
-
Referers: string[] // referer 内容列表列表
|
|
114
|
-
AllowEmpty: boolean // 是否允许空 referer
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export interface ITcbReferer {
|
|
118
|
-
Switch: string // 黑白名单配置开关
|
|
119
|
-
RefererRules?: ITcbRefererRule[]
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export interface ITcbDomainConfig {
|
|
123
|
-
// Origin?: ITcbOrigin // 源域名
|
|
124
|
-
// CosPrivateAccess?: string //是否开始cos私有读
|
|
125
|
-
// Authentication?: ITcbAuthentication // 防盗链设置
|
|
126
|
-
Cache?: ITcbCache[] // 缓存策略
|
|
127
|
-
IpFilter?: IIpFilter // IP 黑白名单配置
|
|
128
|
-
IpFreqLimit?: IIpFreqLimit // IP 限频配置
|
|
129
|
-
Refer?: ITcbReferer
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export interface IModifyOptions {
|
|
133
|
-
domain: string // 域名
|
|
134
|
-
domainId: number // 域名ID
|
|
135
|
-
domainConfig: ITcbDomainConfig // 域名配置
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export interface IDeleteDomainOptions {
|
|
139
|
-
domain: string
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface IDomainInfo {
|
|
143
|
-
Domain: string
|
|
144
|
-
DomainId: number
|
|
145
|
-
Status: 'process' | 'online' | 'offline'
|
|
146
|
-
DomainConfig: Record<string, string>
|
|
147
|
-
CName: String
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const HostingStatusMap = {
|
|
151
|
-
init: '初始化中',
|
|
152
|
-
process: '处理中',
|
|
153
|
-
online: '上线',
|
|
154
|
-
destroying: '销毁中',
|
|
155
|
-
offline: '下线',
|
|
156
|
-
create_fail: '初始化失败', // eslint-disable-line
|
|
157
|
-
destroy_fail: '销毁失败' // eslint-disable-line
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export interface IHostingInfo {
|
|
161
|
-
EnvId: string
|
|
162
|
-
CdnDomain: string
|
|
163
|
-
Bucket: string
|
|
164
|
-
Regoin: string
|
|
165
|
-
Status: string
|
|
166
|
-
MaxDomain: number
|
|
167
|
-
Id: number
|
|
168
|
-
PolicyId: number
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export interface IRoutingRules {
|
|
172
|
-
keyPrefixEquals?: string // 前缀匹配
|
|
173
|
-
httpErrorCodeReturnedEquals?: string // 错误码
|
|
174
|
-
replaceKeyWith?: string // 替换内容
|
|
175
|
-
replaceKeyPrefixWith?: string // condition设置为KeyPrefixEquals 前缀匹配时可设置
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export interface IBucketWebsiteOptiosn {
|
|
179
|
-
indexDocument: string
|
|
180
|
-
errorDocument?: string
|
|
181
|
-
routingRules?: Array<IRoutingRules>
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export interface IFindOptions {
|
|
185
|
-
prefix?: string
|
|
186
|
-
marker?: string
|
|
187
|
-
maxKeys?: number
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export class HostingService {
|
|
191
|
-
private environment: Environment
|
|
192
|
-
private tcbService: CloudService
|
|
193
|
-
private cdnService: CloudService
|
|
194
|
-
|
|
195
|
-
constructor(environment: Environment) {
|
|
196
|
-
this.environment = environment
|
|
197
|
-
this.tcbService = new CloudService(environment.cloudBaseContext, 'tcb', '2018-06-08')
|
|
198
|
-
this.cdnService = new CloudService(environment.cloudBaseContext, 'cdn', '2018-06-06')
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* 获取 hosting 信息
|
|
203
|
-
*/
|
|
204
|
-
@preLazy()
|
|
205
|
-
async getInfo(): Promise<IHostingInfo[]> {
|
|
206
|
-
const { envId } = this.getHostingConfig()
|
|
207
|
-
const { Data } = await this.tcbService.request('DescribeStaticStore', {
|
|
208
|
-
EnvId: envId
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
return Data
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* 开启 hosting 服务,异步任务
|
|
216
|
-
*/
|
|
217
|
-
@preLazy()
|
|
218
|
-
async enableService() {
|
|
219
|
-
const { envId } = this.getHostingConfig()
|
|
220
|
-
|
|
221
|
-
const hostings = await this.getInfo()
|
|
222
|
-
// hosting 服务已开启
|
|
223
|
-
if (hostings?.length) {
|
|
224
|
-
const website = hostings[0]
|
|
225
|
-
// offline 状态的服务可重新开启
|
|
226
|
-
if (website.Status !== 'offline') {
|
|
227
|
-
throw new CloudBaseError('静态网站服务已开启,请勿重复操作!')
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const res = await this.tcbService.request<{
|
|
232
|
-
RequestId: string
|
|
233
|
-
Result: string
|
|
234
|
-
}>('CreateStaticStore', {
|
|
235
|
-
EnvId: envId
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
const code = res.Result === 'succ' ? 0 : -1
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
code,
|
|
242
|
-
requestId: res.RequestId
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
async findFiles(options: IFindOptions): Promise<any> {
|
|
247
|
-
const hosting = await this.checkStatus()
|
|
248
|
-
const { Bucket, Regoin } = hosting
|
|
249
|
-
const { maxKeys, marker, prefix } = options
|
|
250
|
-
|
|
251
|
-
const storageService = await this.environment.getStorageService()
|
|
252
|
-
const res = await storageService.getBucket({
|
|
253
|
-
bucket: Bucket,
|
|
254
|
-
region: Regoin,
|
|
255
|
-
maxKeys,
|
|
256
|
-
marker,
|
|
257
|
-
prefix
|
|
258
|
-
})
|
|
259
|
-
return res
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* 展示文件列表
|
|
264
|
-
*/
|
|
265
|
-
@preLazy()
|
|
266
|
-
async listFiles(): Promise<IListFileInfo[]> {
|
|
267
|
-
const hosting = await this.checkStatus()
|
|
268
|
-
const { Bucket, Regoin } = hosting
|
|
269
|
-
const storageService = await this.environment.getStorageService()
|
|
270
|
-
|
|
271
|
-
const list = await storageService.walkCloudDirCustom({
|
|
272
|
-
prefix: '',
|
|
273
|
-
bucket: Bucket,
|
|
274
|
-
region: Regoin
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
return list
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* 销毁静态托管服务
|
|
282
|
-
*/
|
|
283
|
-
@preLazy()
|
|
284
|
-
async destroyService() {
|
|
285
|
-
const { envId } = this.getHostingConfig()
|
|
286
|
-
|
|
287
|
-
const files = await this.listFiles()
|
|
288
|
-
|
|
289
|
-
if (files?.length) {
|
|
290
|
-
throw new CloudBaseError('静态网站文件不为空,无法销毁!', {
|
|
291
|
-
code: 'INVALID_OPERATION'
|
|
292
|
-
})
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const hostings = await this.getInfo()
|
|
296
|
-
|
|
297
|
-
if (!hostings || !hostings.length) {
|
|
298
|
-
throw new CloudBaseError('静态网站服务未开启!', {
|
|
299
|
-
code: 'INVALID_OPERATION'
|
|
300
|
-
})
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const website = hostings[0]
|
|
304
|
-
|
|
305
|
-
// destroy_fail 状态可重试
|
|
306
|
-
if (website.Status !== 'online' && website.Status !== 'destroy_fail') {
|
|
307
|
-
throw new CloudBaseError(
|
|
308
|
-
`静态网站服务【${HostingStatusMap[website.Status]}】,无法进行此操作!`,
|
|
309
|
-
{
|
|
310
|
-
code: 'INVALID_OPERATION'
|
|
311
|
-
}
|
|
312
|
-
)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const res = await this.tcbService.request<{
|
|
316
|
-
RequestId: string
|
|
317
|
-
Result: string
|
|
318
|
-
}>('DestroyStaticStore', {
|
|
319
|
-
EnvId: envId
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
const code = res.Result === 'succ' ? 0 : -1
|
|
323
|
-
return {
|
|
324
|
-
code,
|
|
325
|
-
requestId: res.RequestId
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* 支持上传单个文件,文件夹,或多个文件
|
|
331
|
-
* @param options
|
|
332
|
-
*/
|
|
333
|
-
@preLazy()
|
|
334
|
-
async uploadFiles(options: IHostingOptions) {
|
|
335
|
-
const {
|
|
336
|
-
localPath,
|
|
337
|
-
cloudPath,
|
|
338
|
-
files = [],
|
|
339
|
-
onProgress,
|
|
340
|
-
onFileFinish,
|
|
341
|
-
parallel = 20,
|
|
342
|
-
ignore,
|
|
343
|
-
retryCount,
|
|
344
|
-
retryInterval
|
|
345
|
-
} = options
|
|
346
|
-
|
|
347
|
-
const hosting = await this.checkStatus()
|
|
348
|
-
const { Bucket, Regoin } = hosting
|
|
349
|
-
const storageService = await this.environment.getStorageService()
|
|
350
|
-
|
|
351
|
-
let uploadFiles = Array.isArray(files) ? files : []
|
|
352
|
-
|
|
353
|
-
// localPath 存在,上传文件夹/文件
|
|
354
|
-
if (localPath) {
|
|
355
|
-
const resolvePath = path.resolve(localPath)
|
|
356
|
-
// 检查路径是否存在
|
|
357
|
-
checkReadable(resolvePath, true)
|
|
358
|
-
|
|
359
|
-
if (isDirectory(resolvePath)) {
|
|
360
|
-
return storageService.uploadDirectoryCustom({
|
|
361
|
-
localPath: resolvePath,
|
|
362
|
-
cloudPath,
|
|
363
|
-
bucket: Bucket,
|
|
364
|
-
region: Regoin,
|
|
365
|
-
onProgress,
|
|
366
|
-
onFileFinish,
|
|
367
|
-
fileId: false,
|
|
368
|
-
ignore,
|
|
369
|
-
retryCount,
|
|
370
|
-
retryInterval,
|
|
371
|
-
})
|
|
372
|
-
} else {
|
|
373
|
-
// 文件上传统一通过批量上传接口
|
|
374
|
-
const assignCloudPath = cloudPath || path.parse(resolvePath).base
|
|
375
|
-
uploadFiles.push({
|
|
376
|
-
localPath: resolvePath,
|
|
377
|
-
cloudPath: assignCloudPath
|
|
378
|
-
})
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// 文件上传统一通过批量上传接口
|
|
383
|
-
return storageService.uploadFilesCustom({
|
|
384
|
-
ignore,
|
|
385
|
-
parallel,
|
|
386
|
-
onProgress,
|
|
387
|
-
onFileFinish,
|
|
388
|
-
bucket: Bucket,
|
|
389
|
-
region: Regoin,
|
|
390
|
-
files: uploadFiles,
|
|
391
|
-
fileId: false,
|
|
392
|
-
retryCount,
|
|
393
|
-
retryInterval,
|
|
394
|
-
})
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* 删除文件或文件夹
|
|
399
|
-
* @param options
|
|
400
|
-
*/
|
|
401
|
-
@preLazy()
|
|
402
|
-
async deleteFiles(options: IHostingCloudOptions) {
|
|
403
|
-
const { cloudPath, isDir } = options
|
|
404
|
-
const hosting = await this.checkStatus()
|
|
405
|
-
const { Bucket, Regoin } = hosting
|
|
406
|
-
const storageService = await this.environment.getStorageService()
|
|
407
|
-
|
|
408
|
-
if (isDir) {
|
|
409
|
-
return storageService.deleteDirectoryCustom({
|
|
410
|
-
cloudPath,
|
|
411
|
-
bucket: Bucket,
|
|
412
|
-
region: Regoin
|
|
413
|
-
})
|
|
414
|
-
} else {
|
|
415
|
-
try {
|
|
416
|
-
await storageService.deleteFileCustom([cloudPath], Bucket, Regoin)
|
|
417
|
-
return {
|
|
418
|
-
Deleted: [{ Key: cloudPath }],
|
|
419
|
-
Error: []
|
|
420
|
-
}
|
|
421
|
-
} catch (e) {
|
|
422
|
-
return {
|
|
423
|
-
Deleted: [],
|
|
424
|
-
Error: [e]
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* 下载文件
|
|
432
|
-
* @param {string} cloudPath 云端文件路径
|
|
433
|
-
* @param {string} localPath 文件本地存储路径,文件需指定文件名称
|
|
434
|
-
* @returns {Promise<NodeJS.ReadableStream>}
|
|
435
|
-
*/
|
|
436
|
-
@preLazy()
|
|
437
|
-
public async downloadFile(options: {
|
|
438
|
-
cloudPath: string
|
|
439
|
-
localPath?: string
|
|
440
|
-
}): Promise<NodeJS.ReadableStream | string> {
|
|
441
|
-
const { cloudPath, localPath } = options
|
|
442
|
-
const resolveLocalPath = path.resolve(localPath)
|
|
443
|
-
const fileDir = path.dirname(localPath)
|
|
444
|
-
|
|
445
|
-
checkFullAccess(fileDir, true)
|
|
446
|
-
|
|
447
|
-
const envConfig = this.environment.lazyEnvironmentConfig
|
|
448
|
-
const cacheHosting: IHostingInfo & { cacheTime: number } = envDomainCache.get(
|
|
449
|
-
envConfig.EnvId
|
|
450
|
-
)
|
|
451
|
-
|
|
452
|
-
let CdnDomain
|
|
453
|
-
// 2 分钟有效
|
|
454
|
-
if (cacheHosting?.cacheTime && Number(cacheHosting?.cacheTime) + 120000 < Date.now()) {
|
|
455
|
-
console.log('cache')
|
|
456
|
-
CdnDomain = cacheHosting.CdnDomain
|
|
457
|
-
} else {
|
|
458
|
-
const hosting = await this.checkStatus()
|
|
459
|
-
CdnDomain = hosting.CdnDomain
|
|
460
|
-
envDomainCache.set(envConfig.EnvId, {
|
|
461
|
-
...hosting,
|
|
462
|
-
cacheTime: Date.now()
|
|
463
|
-
})
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
const url = new URL(cloudPath, `https://${CdnDomain}`).toString()
|
|
467
|
-
|
|
468
|
-
const { proxy } = await this.environment.getAuthConfig()
|
|
469
|
-
const res = await fetchStream(url, {}, proxy)
|
|
470
|
-
|
|
471
|
-
// localPath 不存在时,返回 ReadableStream
|
|
472
|
-
if (!localPath) {
|
|
473
|
-
return res.body
|
|
474
|
-
}
|
|
475
|
-
const dest = fs.createWriteStream(resolveLocalPath)
|
|
476
|
-
res.body.pipe(dest)
|
|
477
|
-
|
|
478
|
-
// 写完成后返回
|
|
479
|
-
return new Promise(resolve => {
|
|
480
|
-
dest.on('close', () => {
|
|
481
|
-
// 返回文件地址
|
|
482
|
-
resolve(resolveLocalPath)
|
|
483
|
-
})
|
|
484
|
-
})
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/**
|
|
488
|
-
* 下载文件夹
|
|
489
|
-
* @param {string} cloudPath 云端文件路径
|
|
490
|
-
* @param {string} localPath 本地文件夹存储路径
|
|
491
|
-
* @returns {Promise<(NodeJS.ReadableStream | string)[]>}
|
|
492
|
-
*/
|
|
493
|
-
@preLazy()
|
|
494
|
-
public async downloadDirectory(options: {
|
|
495
|
-
cloudPath: string
|
|
496
|
-
localPath?: string
|
|
497
|
-
}): Promise<void> {
|
|
498
|
-
const { cloudPath, localPath } = options
|
|
499
|
-
const resolveLocalPath = path.resolve(localPath)
|
|
500
|
-
|
|
501
|
-
const hosting = await this.checkStatus()
|
|
502
|
-
const { Bucket, Regoin } = hosting
|
|
503
|
-
|
|
504
|
-
const cloudDirectoryKey = this.getCloudKey(cloudPath)
|
|
505
|
-
const storageService = await this.environment.getStorageService()
|
|
506
|
-
const files = await storageService.walkCloudDirCustom({
|
|
507
|
-
prefix: cloudDirectoryKey,
|
|
508
|
-
bucket: Bucket,
|
|
509
|
-
region: Regoin
|
|
510
|
-
})
|
|
511
|
-
|
|
512
|
-
const tasks = files.map(file => async () => {
|
|
513
|
-
const fileRelativePath = file.Key.replace(cloudDirectoryKey, '')
|
|
514
|
-
// 空路径和文件夹跳过
|
|
515
|
-
if (!fileRelativePath || /\/$/g.test(fileRelativePath)) {
|
|
516
|
-
return
|
|
517
|
-
}
|
|
518
|
-
const localFilePath = path.join(resolveLocalPath, fileRelativePath)
|
|
519
|
-
// 创建文件的父文件夹
|
|
520
|
-
const fileDir = path.dirname(localFilePath)
|
|
521
|
-
await makeDir(fileDir)
|
|
522
|
-
return this.downloadFile({
|
|
523
|
-
cloudPath: file.Key,
|
|
524
|
-
localPath: localFilePath
|
|
525
|
-
})
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
// 下载请求
|
|
529
|
-
const creatingDirController = new AsyncTaskParallelController(20, 50)
|
|
530
|
-
creatingDirController.loadTasks(tasks)
|
|
531
|
-
await creatingDirController.run()
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// 遍历文件
|
|
535
|
-
@preLazy()
|
|
536
|
-
async walkLocalDir(envId: string, dir: string) {
|
|
537
|
-
const storageService = await this.environment.getStorageService()
|
|
538
|
-
return storageService.walkLocalDir(dir)
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* 绑定自定义域名
|
|
543
|
-
* @param {IBindDomainOptions} options
|
|
544
|
-
* @returns
|
|
545
|
-
* @memberof HostingService
|
|
546
|
-
*/
|
|
547
|
-
@preLazy()
|
|
548
|
-
async CreateHostingDomain(options: IBindDomainOptions) {
|
|
549
|
-
const { envId } = this.getHostingConfig()
|
|
550
|
-
const { certId, domain } = options
|
|
551
|
-
const res = await this.tcbService.request('CreateHostingDomain', {
|
|
552
|
-
EnvId: envId,
|
|
553
|
-
Domain: domain,
|
|
554
|
-
CertId: certId
|
|
555
|
-
})
|
|
556
|
-
|
|
557
|
-
return res
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* 删除托管域名
|
|
562
|
-
*
|
|
563
|
-
* @param {IBindDomainOptions} options
|
|
564
|
-
* @returns
|
|
565
|
-
* @memberof HostingService
|
|
566
|
-
*/
|
|
567
|
-
@preLazy()
|
|
568
|
-
async deleteHostingDomain(options: IDeleteDomainOptions) {
|
|
569
|
-
const { envId } = this.getHostingConfig()
|
|
570
|
-
const { domain } = options
|
|
571
|
-
return this.tcbService.request<{ RequestId: string }>('DeleteHostingDomain', {
|
|
572
|
-
EnvId: envId,
|
|
573
|
-
Domain: domain
|
|
574
|
-
})
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
/**
|
|
578
|
-
* 查询域名状态信息
|
|
579
|
-
* @param options
|
|
580
|
-
*/
|
|
581
|
-
async tcbCheckResource(options: ICheckSourceOptions) {
|
|
582
|
-
return this.cdnService.request<{
|
|
583
|
-
Domains: IDomainInfo[]
|
|
584
|
-
RecordCount: number
|
|
585
|
-
RequestId: string
|
|
586
|
-
}>('TcbCheckResource', {
|
|
587
|
-
Domains: options.domains
|
|
588
|
-
})
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
/**
|
|
592
|
-
* 域名配置变更
|
|
593
|
-
* @param options
|
|
594
|
-
*/
|
|
595
|
-
async tcbModifyAttribute(options: IModifyOptions) {
|
|
596
|
-
const { domain, domainId, domainConfig } = options
|
|
597
|
-
|
|
598
|
-
const res = await this.cdnService.request('TcbModifyAttribute', {
|
|
599
|
-
Domain: domain,
|
|
600
|
-
DomainId: domainId,
|
|
601
|
-
DomainConfig: domainConfig
|
|
602
|
-
})
|
|
603
|
-
return res
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/**
|
|
607
|
-
* 查询静态网站配置
|
|
608
|
-
* @memberof HostingService
|
|
609
|
-
*/
|
|
610
|
-
async getWebsiteConfig() {
|
|
611
|
-
const hosting = await this.checkStatus()
|
|
612
|
-
const { Bucket, Regoin } = hosting
|
|
613
|
-
const storageService = await this.environment.getStorageService()
|
|
614
|
-
const res = await storageService.getWebsiteConfig({ bucket: Bucket, region: Regoin })
|
|
615
|
-
return res
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* 配置静态网站文档
|
|
620
|
-
* @param options
|
|
621
|
-
*/
|
|
622
|
-
async setWebsiteDocument(options: IBucketWebsiteOptiosn) {
|
|
623
|
-
const { indexDocument, errorDocument, routingRules } = options
|
|
624
|
-
const hosting = await this.checkStatus()
|
|
625
|
-
const { Bucket, Regoin } = hosting
|
|
626
|
-
|
|
627
|
-
const storageService = await this.environment.getStorageService()
|
|
628
|
-
const res = await storageService.putBucketWebsite({
|
|
629
|
-
bucket: Bucket,
|
|
630
|
-
region: Regoin,
|
|
631
|
-
indexDocument,
|
|
632
|
-
errorDocument,
|
|
633
|
-
routingRules
|
|
634
|
-
})
|
|
635
|
-
return res
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* 检查 hosting 服务状态
|
|
640
|
-
*/
|
|
641
|
-
@preLazy()
|
|
642
|
-
private async checkStatus() {
|
|
643
|
-
const hostings = await this.getInfo()
|
|
644
|
-
|
|
645
|
-
if (!hostings || !hostings.length) {
|
|
646
|
-
throw new CloudBaseError(
|
|
647
|
-
`您还没有开启静态网站服务,请先到云开发控制台开启静态网站服务!`,
|
|
648
|
-
{
|
|
649
|
-
code: 'INVALID_OPERATION'
|
|
650
|
-
}
|
|
651
|
-
)
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
const website = hostings[0]
|
|
655
|
-
|
|
656
|
-
if (website.Status !== 'online') {
|
|
657
|
-
throw new CloudBaseError(
|
|
658
|
-
`静态网站服务【${HostingStatusMap[website.Status]}】,无法进行此操作!`,
|
|
659
|
-
{
|
|
660
|
-
code: 'INVALID_OPERATION'
|
|
661
|
-
}
|
|
662
|
-
)
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
return website
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
/**
|
|
669
|
-
* 获取配置
|
|
670
|
-
*/
|
|
671
|
-
private getHostingConfig() {
|
|
672
|
-
const envConfig = this.environment.lazyEnvironmentConfig
|
|
673
|
-
const appId = envConfig.Storages[0]?.AppId
|
|
674
|
-
const { proxy } = this.environment.cloudBaseContext
|
|
675
|
-
|
|
676
|
-
return {
|
|
677
|
-
appId,
|
|
678
|
-
proxy,
|
|
679
|
-
envId: envConfig.EnvId
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
/**
|
|
684
|
-
* 将 cloudPath 转换成 cloudPath/ 形式
|
|
685
|
-
*/
|
|
686
|
-
private getCloudKey(cloudPath: string): string {
|
|
687
|
-
if (!cloudPath) {
|
|
688
|
-
return ''
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
// 单个 / 转换成根目录
|
|
692
|
-
if (cloudPath === '/') {
|
|
693
|
-
return ''
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
return cloudPath[cloudPath.length - 1] === '/' ? cloudPath : `${cloudPath}/`
|
|
697
|
-
}
|
|
698
|
-
}
|