@cloudbase/cli 2.0.3 → 2.0.4-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 (199) hide show
  1. package/.editorconfig +9 -9
  2. package/.eslintignore +7 -7
  3. package/.eslintrc +35 -35
  4. package/.prettierrc.js +29 -29
  5. package/.vscode/launch.json +16 -16
  6. package/LICENSE +5 -5
  7. package/README.md +35 -35
  8. package/bin/cloudbase.js +5 -5
  9. package/bin/tcb.js +0 -0
  10. package/changelog.md +6 -6
  11. package/jest.config.js +17 -17
  12. package/lib/commands/account/login.js +18 -18
  13. package/lib/commands/storage/storage.js +1 -1
  14. package/lib/env/login.js +7 -7
  15. package/package.json +2 -2
  16. package/post-install.js +61 -61
  17. package/runtime/nodejs/bootstrap.js +255 -255
  18. package/runtime/nodejs/runtime.js +183 -183
  19. package/src/auth/index.ts +1 -1
  20. package/src/auth/login.ts +91 -91
  21. package/src/auth/logout.ts +7 -7
  22. package/src/commands/account/index.ts +2 -2
  23. package/src/commands/account/login.ts +192 -192
  24. package/src/commands/account/logout.ts +24 -24
  25. package/src/commands/env/base.ts +90 -90
  26. package/src/commands/env/create.ts +92 -92
  27. package/src/commands/env/domain.ts +186 -186
  28. package/src/commands/env/index.ts +4 -4
  29. package/src/commands/env/login.ts +235 -235
  30. package/src/commands/framework/index.ts +124 -124
  31. package/src/commands/functions/alias/getRoute.ts +76 -76
  32. package/src/commands/functions/alias/index.ts +2 -2
  33. package/src/commands/functions/alias/setRoute.ts +82 -82
  34. package/src/commands/functions/code-download.ts +100 -100
  35. package/src/commands/functions/code-update.ts +62 -62
  36. package/src/commands/functions/concurrency/delete.ts +45 -45
  37. package/src/commands/functions/concurrency/index.ts +2 -2
  38. package/src/commands/functions/concurrency/list.ts +58 -58
  39. package/src/commands/functions/concurrency/set.ts +47 -47
  40. package/src/commands/functions/config-update.ts +76 -76
  41. package/src/commands/functions/copy.ts +62 -62
  42. package/src/commands/functions/delete.ts +79 -79
  43. package/src/commands/functions/deploy.ts +293 -293
  44. package/src/commands/functions/detail.ts +138 -138
  45. package/src/commands/functions/index.ts +16 -16
  46. package/src/commands/functions/invoke.ts +121 -121
  47. package/src/commands/functions/layer/bind.ts +182 -182
  48. package/src/commands/functions/layer/common.ts +8 -8
  49. package/src/commands/functions/layer/create.ts +49 -49
  50. package/src/commands/functions/layer/delete.ts +73 -73
  51. package/src/commands/functions/layer/download.ts +92 -92
  52. package/src/commands/functions/layer/index.ts +7 -7
  53. package/src/commands/functions/layer/list.ts +94 -94
  54. package/src/commands/functions/layer/sort.ts +76 -76
  55. package/src/commands/functions/list.ts +68 -68
  56. package/src/commands/functions/log.ts +148 -148
  57. package/src/commands/functions/run.ts +249 -249
  58. package/src/commands/functions/trigger-create.ts +79 -79
  59. package/src/commands/functions/trigger-delete.ts +105 -105
  60. package/src/commands/functions/version/index.ts +1 -1
  61. package/src/commands/functions/version/list.ts +73 -73
  62. package/src/commands/functions/version/publish.ts +43 -43
  63. package/src/commands/gateway/create.ts +109 -109
  64. package/src/commands/gateway/delete.ts +81 -81
  65. package/src/commands/gateway/domain.ts +159 -159
  66. package/src/commands/gateway/index.ts +5 -5
  67. package/src/commands/gateway/list.ts +76 -76
  68. package/src/commands/gateway/switch.ts +107 -107
  69. package/src/commands/helpers/index.ts +2 -2
  70. package/src/commands/helpers/init.ts +431 -431
  71. package/src/commands/helpers/new.ts +117 -117
  72. package/src/commands/helpers/open.ts +67 -67
  73. package/src/commands/hosting/hosting.ts +360 -360
  74. package/src/commands/index.ts +13 -13
  75. package/src/commands/lowcode/app.ts +34 -34
  76. package/src/commands/lowcode/comps.ts +322 -322
  77. package/src/commands/lowcode/index.ts +1 -1
  78. package/src/commands/lowcode/utils.ts +24 -24
  79. package/src/commands/run/image/index.ts +4 -4
  80. package/src/commands/run/standalonegateway/common.ts +7 -7
  81. package/src/commands/run/standalonegateway/create.ts +85 -85
  82. package/src/commands/run/standalonegateway/destroy.ts +59 -59
  83. package/src/commands/run/standalonegateway/index.ts +4 -4
  84. package/src/commands/run/standalonegateway/list.ts +53 -53
  85. package/src/commands/run/standalonegateway/package.ts +62 -62
  86. package/src/commands/run/standalonegateway/turn.ts +63 -63
  87. package/src/commands/run/version/index.ts +4 -4
  88. package/src/commands/smart.ts +132 -132
  89. package/src/commands/storage/storage.ts +464 -464
  90. package/src/commands/third/thirdAttach.ts +49 -49
  91. package/src/completion/index.ts +13 -13
  92. package/src/decorators/captureError.ts +25 -25
  93. package/src/decorators/constants.ts +12 -12
  94. package/src/decorators/deprecate.ts +25 -25
  95. package/src/decorators/guard.ts +42 -42
  96. package/src/decorators/index.ts +7 -7
  97. package/src/decorators/injectParams.ts +54 -54
  98. package/src/decorators/params/common.ts +28 -28
  99. package/src/decorators/params/index.ts +35 -35
  100. package/src/env/domain.ts +33 -33
  101. package/src/env/index.ts +63 -63
  102. package/src/env/login.ts +80 -80
  103. package/src/error.ts +36 -36
  104. package/src/function/alias.ts +43 -43
  105. package/src/function/base.ts +253 -253
  106. package/src/function/code.ts +55 -55
  107. package/src/function/concurrency.ts +57 -57
  108. package/src/function/create.ts +78 -78
  109. package/src/function/delete.ts +42 -42
  110. package/src/function/index.ts +10 -10
  111. package/src/function/layer/attach.ts +68 -68
  112. package/src/function/layer/create.ts +63 -63
  113. package/src/function/layer/delete.ts +21 -21
  114. package/src/function/layer/download.ts +54 -54
  115. package/src/function/layer/index.ts +7 -7
  116. package/src/function/layer/list.ts +32 -32
  117. package/src/function/layer/sort.ts +24 -24
  118. package/src/function/trigger.ts +97 -97
  119. package/src/function/update.ts +35 -35
  120. package/src/function/version.ts +38 -38
  121. package/src/function/vpc.ts +22 -22
  122. package/src/gateway/index.ts +137 -137
  123. package/src/hosting.ts +212 -212
  124. package/src/index.ts +13 -13
  125. package/src/logger.ts +17 -17
  126. package/src/run/create.ts +23 -23
  127. package/src/run/delete.ts +15 -15
  128. package/src/run/image/build.ts +36 -36
  129. package/src/run/image/delete.ts +13 -13
  130. package/src/run/image/index.ts +3 -3
  131. package/src/run/image/info.ts +26 -26
  132. package/src/run/list.ts +29 -29
  133. package/src/run/repo.ts +24 -24
  134. package/src/run/standalonegateway/create.ts +24 -24
  135. package/src/run/standalonegateway/destroy.ts +19 -19
  136. package/src/run/standalonegateway/index.ts +4 -4
  137. package/src/run/standalonegateway/list.ts +74 -74
  138. package/src/run/standalonegateway/package/list.ts +24 -24
  139. package/src/run/standalonegateway/turn/index.ts +1 -1
  140. package/src/run/standalonegateway/turn/off.ts +19 -19
  141. package/src/run/standalonegateway/turn/on.ts +19 -19
  142. package/src/run/version/create.ts +68 -68
  143. package/src/run/version/delete.ts +15 -15
  144. package/src/run/version/index.ts +5 -5
  145. package/src/run/version/list.ts +16 -16
  146. package/src/run/version/modify.ts +16 -16
  147. package/src/run/version/repo.ts +27 -27
  148. package/src/run/version/update.ts +58 -58
  149. package/src/storage.ts +114 -114
  150. package/src/third/index.ts +12 -12
  151. package/src/utils/auth.ts +15 -15
  152. package/src/utils/cli-table.ts +23 -23
  153. package/src/utils/config.ts +39 -39
  154. package/src/utils/env.ts +244 -244
  155. package/src/utils/fs/del.ts +5 -5
  156. package/src/utils/fs/index.ts +71 -71
  157. package/src/utils/function-packer.ts +97 -97
  158. package/src/utils/log.ts +81 -81
  159. package/src/utils/net/cloud-api-request.ts +62 -62
  160. package/src/utils/net/credential.ts +53 -53
  161. package/src/utils/net/index.ts +4 -4
  162. package/src/utils/net/manager-service.ts +36 -36
  163. package/src/utils/net/proxy.ts +6 -6
  164. package/src/utils/notice.ts +28 -28
  165. package/src/utils/output/highlight.ts +5 -5
  166. package/src/utils/output/index.ts +2 -2
  167. package/src/utils/output/link.ts +10 -10
  168. package/src/utils/output/loading.ts +82 -82
  169. package/src/utils/parallel.ts +82 -82
  170. package/src/utils/platform/index.ts +2 -2
  171. package/src/utils/platform/mac.ts +21 -21
  172. package/src/utils/platform/os.ts +64 -64
  173. package/src/utils/platform/port.ts +10 -10
  174. package/src/utils/progress-bar.ts +38 -38
  175. package/src/utils/prompt/select.ts +59 -59
  176. package/src/utils/reporter/agree.ts +20 -20
  177. package/src/utils/reporter/download.ts +26 -26
  178. package/src/utils/reporter/index.ts +3 -3
  179. package/src/utils/reporter/usage.ts +20 -20
  180. package/src/utils/store/auth.ts +49 -49
  181. package/src/utils/store/common.ts +8 -8
  182. package/src/utils/store/db.ts +68 -68
  183. package/src/utils/store/index.ts +4 -4
  184. package/src/utils/store/usage.ts +12 -12
  185. package/src/utils/template.ts +170 -170
  186. package/src/utils/tools/encoding.ts +8 -8
  187. package/src/utils/tools/index.ts +4 -4
  188. package/src/utils/tools/object.ts +33 -33
  189. package/src/utils/tools/time.ts +38 -38
  190. package/src/utils/tools/uid.ts +19 -19
  191. package/templates/html/loginFail.html +90 -90
  192. package/templates/html/loginSuccess.html +86 -86
  193. package/templates/server/node/_gitignore +54 -54
  194. package/templates/server/node/cloudbaserc.json +10 -10
  195. package/templates/server/node/index.js +5 -5
  196. package/templates/server/node/package.json +9 -9
  197. package/tsconfig.json +19 -19
  198. package/tsconfig.test.json +13 -13
  199. package/.vscode/settings.json +0 -3
@@ -1,293 +1,293 @@
1
- import path from 'path'
2
- import inquirer from 'inquirer'
3
- import { getRegion } from '@cloudbase/toolbox'
4
- import { Command, ICommand } from '../common'
5
- import { CloudBaseError } from '../../error'
6
- import { createFunction } from '../../function'
7
- import { queryGateway, createGateway } from '../../gateway'
8
- import {
9
- logger,
10
- random,
11
- isDirectory,
12
- loadingFactory,
13
- genClickableLink,
14
- highlightCommand,
15
- checkFullAccess,
16
- AsyncTaskParallelController
17
- } from '../../utils'
18
- import { ICreateFunctionOptions } from '../../types'
19
- import { DefaultFunctionDeployConfig } from '../../constant'
20
- import { InjectParams, CmdContext, ArgsParams, Log, Logger } from '../../decorators'
21
-
22
- const regionIdMap = {
23
- 'ap-guangzhou': 1,
24
- 'ap-shanghai': 4,
25
- 'ap-beijing': 8
26
- }
27
-
28
- @ICommand()
29
- export class FunctionDeploy extends Command {
30
- get options() {
31
- return {
32
- cmd: 'fn',
33
- childCmd: 'deploy [name]',
34
- deprecateCmd: 'functions:deploy [name]',
35
- options: [
36
- {
37
- flags: '-e, --envId <envId>',
38
- desc: '环境 Id'
39
- },
40
- {
41
- flags: '--code-secret <codeSecret>',
42
- desc: '传入此参数将保护代码,格式为 36 位大小写字母和数字'
43
- },
44
- {
45
- flags: '--force',
46
- desc: '如果存在同名函数,上传后覆盖同名函数'
47
- },
48
- {
49
- flags: '--path <path>',
50
- desc: '自动创建HTTP 访问服务访问路径'
51
- },
52
- {
53
- flags: '--all',
54
- desc: '部署配置文件中的包含的全部云函数'
55
- },
56
- {
57
- flags: '--dir <dir>',
58
- desc: '指定云函数的文件夹路径'
59
- }
60
- ],
61
- desc: '部署云函数'
62
- }
63
- }
64
-
65
- @InjectParams()
66
- async execute(@CmdContext() ctx, @ArgsParams() params, @Log() log: Logger) {
67
- const { envId, config, options } = ctx
68
- const { functions } = config
69
- const { force, codeSecret, path: access, all, dir } = options
70
- const functionRootPath = path.join(process.cwd(), config.functionRoot)
71
- const name = params?.[0]
72
-
73
- if (access && checkFullAccess(access)) {
74
- log.warn('--path 参数已更换为HTTP 访问服务路径,请使用 --dir 指定部署函数的文件夹路径')
75
- }
76
-
77
- if (access && access[0] !== '/') {
78
- throw new CloudBaseError('HTTP 访问服务路径必须以 / 开头')
79
- }
80
-
81
- // 当没有指定函数名称或函数路径时,询问处理否部署全部云函数
82
- if ((!name && !dir) || all) {
83
- return this.deployAllFunction({
84
- all,
85
- envId,
86
- force,
87
- access,
88
- functions,
89
- codeSecret,
90
- functionRootPath
91
- })
92
- }
93
-
94
- // 校验函数路径是否存在
95
- if (dir) {
96
- checkFullAccess(dir, true)
97
- if (!isDirectory(dir)) {
98
- throw new CloudBaseError('--dir 参数必须指定为云函数的文件夹路径')
99
- }
100
- }
101
-
102
- let newFunction
103
- if (functions && functions.length > 0) {
104
- newFunction = functions.find((item) => item.name === name)
105
- }
106
-
107
- // 没有配置,使用默认配置
108
- if (!newFunction || !newFunction.name) {
109
- log.info('未找到函数发布配置,使用默认配置 => 运行时:Nodejs10.15/在线安装依赖')
110
- newFunction = {
111
- name,
112
- ...DefaultFunctionDeployConfig
113
- }
114
- }
115
-
116
- const loading = loadingFactory()
117
-
118
- loading.start('云函数部署中...')
119
-
120
- try {
121
- await createFunction({
122
- force,
123
- envId,
124
- codeSecret,
125
- functionRootPath,
126
- func: newFunction,
127
- accessPath: access,
128
- functionPath: dir
129
- })
130
- loading.succeed(`[${newFunction.name}] 云函数部署成功!`)
131
- // await genApiGateway(envId, name)
132
- this.printSuccessTips(envId)
133
- } catch (e) {
134
- // 询问是否覆盖同名函数
135
- loading.stop()
136
- await this.handleDeployFail(e, {
137
- envId,
138
- codeSecret,
139
- functionRootPath,
140
- func: newFunction,
141
- accessPath: access,
142
- functionPath: dir
143
- })
144
- }
145
-
146
- if (access || newFunction.path) {
147
- const link = genClickableLink(
148
- `https://${envId}.service.tcloudbase.com${access || newFunction.path}`
149
- )
150
- console.log(`\n云函数HTTP 访问服务访问链接:${link}`)
151
- }
152
- }
153
-
154
- async deployAllFunction(options: any) {
155
- const { functions = [], envId, force, codeSecret, functionRootPath, all, access } = options
156
-
157
- // 指定 all 参数,直接部署全部云函数
158
- if (!all) {
159
- const { isBatch } = await inquirer.prompt({
160
- type: 'confirm',
161
- name: 'isBatch',
162
- message: '没有指定需要部署的云函数,是否部署配置文件中的全部云函数?',
163
- default: false
164
- })
165
-
166
- // 用户不部署全部函数,报错
167
- if (!isBatch) {
168
- throw new CloudBaseError(
169
- '请指定需要部署的云函数的名称或通过 --path 参数指定需要部署的函数的路径!'
170
- )
171
- }
172
- }
173
-
174
- // 批量部署云函数
175
- const loading = loadingFactory()
176
- const tasks = functions.map((func) => async () => {
177
- loading.start('云函数部署中')
178
- try {
179
- await createFunction({
180
- func,
181
- envId,
182
- force,
183
- codeSecret,
184
- functionRootPath,
185
- accessPath: access
186
- })
187
- loading.succeed(`[${func.name}] 云函数部署成功`)
188
- } catch (e) {
189
- loading.stop()
190
- await this.handleDeployFail(e, {
191
- func,
192
- envId,
193
- codeSecret,
194
- functionRootPath,
195
- accessPath: access
196
- })
197
- }
198
- })
199
-
200
- if (tasks.length > 5) {
201
- logger.info('函数数量较多,将使用队列部署')
202
- }
203
-
204
- // 控制函数创建并发
205
- const asyncTaskController = new AsyncTaskParallelController(5, 50)
206
- asyncTaskController.loadTasks(tasks)
207
- const results = await asyncTaskController.run()
208
-
209
- // 输出信息
210
- const success = results.filter((_) => !_)
211
- logger.success(`成功部署 ${success?.length} 个函数`)
212
- // 部署失败
213
- const err = results.filter((_) => _)
214
- err?.length && logger.error(`${err?.length} 个云函数部署失败`)
215
- }
216
-
217
- async handleDeployFail(e: CloudBaseError, options: ICreateFunctionOptions) {
218
- const { envId, codeSecret, functionRootPath, func, functionPath, accessPath } = options
219
- const loading = loadingFactory()
220
-
221
- if (e.code === 'ResourceInUse.FunctionName' || e.code === 'ResourceInUse.Function') {
222
- const { force } = await inquirer.prompt({
223
- type: 'confirm',
224
- name: 'force',
225
- message: `存在同名云函数:[${func.name}],是否覆盖原函数代码与配置`,
226
- default: false
227
- })
228
-
229
- if (force) {
230
- loading.start('云函数部署中...')
231
- try {
232
- await createFunction({
233
- func,
234
- envId,
235
- codeSecret,
236
- accessPath,
237
- force: true,
238
- functionPath,
239
- functionRootPath
240
- })
241
- loading.succeed(`[${func.name}] 云函数部署成功!`)
242
- // await genApiGateway(envId, name)
243
- await this.printSuccessTips(envId)
244
- } catch (e) {
245
- loading.stop()
246
- throw e
247
- }
248
- return
249
- }
250
- }
251
-
252
- throw e
253
- }
254
-
255
- @InjectParams()
256
- async printSuccessTips(envId: string, @Log() log?: Logger) {
257
- let url = `https://console.cloud.tencent.com/tcb/scf?envId=${envId}`
258
- const region = await getRegion()
259
- url += `&rid=${regionIdMap[region]}`
260
- const link = genClickableLink(url)
261
- log.breakLine()
262
- log.info(`控制台查看函数详情或创建HTTP 访问服务链接 🔗:${link}`)
263
- log.info(`使用 ${highlightCommand('cloudbase functions:list')} 命令查看已部署云函数`)
264
- }
265
-
266
- // 创建函数 API 网关
267
- async genApiGateway(envId: string, name: string) {
268
- const loading = loadingFactory()
269
- // 检查是否绑定了 HTTP 网关
270
- const res = await queryGateway({
271
- name,
272
- envId
273
- })
274
- // 未开启,不生成 HTTP 调用了链接
275
- if (res?.EnableService === false) return
276
- loading.start('生成云函数HTTP 访问服务中...')
277
-
278
- let path
279
- if (res?.APISet?.length > 0) {
280
- path = res.APISet[0]?.Path
281
- } else {
282
- path = `/${random(12)}`
283
- await createGateway({
284
- envId,
285
- name,
286
- path
287
- })
288
- }
289
- loading.stop()
290
- const link = genClickableLink(`https://${envId}.service.tcloudbase.com${path}`)
291
- console.log(`\n云函数HTTP 访问服务链接:${link}`)
292
- }
293
- }
1
+ import path from 'path'
2
+ import inquirer from 'inquirer'
3
+ import { getRegion } from '@cloudbase/toolbox'
4
+ import { Command, ICommand } from '../common'
5
+ import { CloudBaseError } from '../../error'
6
+ import { createFunction } from '../../function'
7
+ import { queryGateway, createGateway } from '../../gateway'
8
+ import {
9
+ logger,
10
+ random,
11
+ isDirectory,
12
+ loadingFactory,
13
+ genClickableLink,
14
+ highlightCommand,
15
+ checkFullAccess,
16
+ AsyncTaskParallelController
17
+ } from '../../utils'
18
+ import { ICreateFunctionOptions } from '../../types'
19
+ import { DefaultFunctionDeployConfig } from '../../constant'
20
+ import { InjectParams, CmdContext, ArgsParams, Log, Logger } from '../../decorators'
21
+
22
+ const regionIdMap = {
23
+ 'ap-guangzhou': 1,
24
+ 'ap-shanghai': 4,
25
+ 'ap-beijing': 8
26
+ }
27
+
28
+ @ICommand()
29
+ export class FunctionDeploy extends Command {
30
+ get options() {
31
+ return {
32
+ cmd: 'fn',
33
+ childCmd: 'deploy [name]',
34
+ deprecateCmd: 'functions:deploy [name]',
35
+ options: [
36
+ {
37
+ flags: '-e, --envId <envId>',
38
+ desc: '环境 Id'
39
+ },
40
+ {
41
+ flags: '--code-secret <codeSecret>',
42
+ desc: '传入此参数将保护代码,格式为 36 位大小写字母和数字'
43
+ },
44
+ {
45
+ flags: '--force',
46
+ desc: '如果存在同名函数,上传后覆盖同名函数'
47
+ },
48
+ {
49
+ flags: '--path <path>',
50
+ desc: '自动创建HTTP 访问服务访问路径'
51
+ },
52
+ {
53
+ flags: '--all',
54
+ desc: '部署配置文件中的包含的全部云函数'
55
+ },
56
+ {
57
+ flags: '--dir <dir>',
58
+ desc: '指定云函数的文件夹路径'
59
+ }
60
+ ],
61
+ desc: '部署云函数'
62
+ }
63
+ }
64
+
65
+ @InjectParams()
66
+ async execute(@CmdContext() ctx, @ArgsParams() params, @Log() log: Logger) {
67
+ const { envId, config, options } = ctx
68
+ const { functions } = config
69
+ const { force, codeSecret, path: access, all, dir } = options
70
+ const functionRootPath = path.join(process.cwd(), config.functionRoot)
71
+ const name = params?.[0]
72
+
73
+ if (access && checkFullAccess(access)) {
74
+ log.warn('--path 参数已更换为HTTP 访问服务路径,请使用 --dir 指定部署函数的文件夹路径')
75
+ }
76
+
77
+ if (access && access[0] !== '/') {
78
+ throw new CloudBaseError('HTTP 访问服务路径必须以 / 开头')
79
+ }
80
+
81
+ // 当没有指定函数名称或函数路径时,询问处理否部署全部云函数
82
+ if ((!name && !dir) || all) {
83
+ return this.deployAllFunction({
84
+ all,
85
+ envId,
86
+ force,
87
+ access,
88
+ functions,
89
+ codeSecret,
90
+ functionRootPath
91
+ })
92
+ }
93
+
94
+ // 校验函数路径是否存在
95
+ if (dir) {
96
+ checkFullAccess(dir, true)
97
+ if (!isDirectory(dir)) {
98
+ throw new CloudBaseError('--dir 参数必须指定为云函数的文件夹路径')
99
+ }
100
+ }
101
+
102
+ let newFunction
103
+ if (functions && functions.length > 0) {
104
+ newFunction = functions.find((item) => item.name === name)
105
+ }
106
+
107
+ // 没有配置,使用默认配置
108
+ if (!newFunction || !newFunction.name) {
109
+ log.info('未找到函数发布配置,使用默认配置 => 运行时:Nodejs10.15/在线安装依赖')
110
+ newFunction = {
111
+ name,
112
+ ...DefaultFunctionDeployConfig
113
+ }
114
+ }
115
+
116
+ const loading = loadingFactory()
117
+
118
+ loading.start('云函数部署中...')
119
+
120
+ try {
121
+ await createFunction({
122
+ force,
123
+ envId,
124
+ codeSecret,
125
+ functionRootPath,
126
+ func: newFunction,
127
+ accessPath: access,
128
+ functionPath: dir
129
+ })
130
+ loading.succeed(`[${newFunction.name}] 云函数部署成功!`)
131
+ // await genApiGateway(envId, name)
132
+ this.printSuccessTips(envId)
133
+ } catch (e) {
134
+ // 询问是否覆盖同名函数
135
+ loading.stop()
136
+ await this.handleDeployFail(e, {
137
+ envId,
138
+ codeSecret,
139
+ functionRootPath,
140
+ func: newFunction,
141
+ accessPath: access,
142
+ functionPath: dir
143
+ })
144
+ }
145
+
146
+ if (access || newFunction.path) {
147
+ const link = genClickableLink(
148
+ `https://${envId}.service.tcloudbase.com${access || newFunction.path}`
149
+ )
150
+ console.log(`\n云函数HTTP 访问服务访问链接:${link}`)
151
+ }
152
+ }
153
+
154
+ async deployAllFunction(options: any) {
155
+ const { functions = [], envId, force, codeSecret, functionRootPath, all, access } = options
156
+
157
+ // 指定 all 参数,直接部署全部云函数
158
+ if (!all) {
159
+ const { isBatch } = await inquirer.prompt({
160
+ type: 'confirm',
161
+ name: 'isBatch',
162
+ message: '没有指定需要部署的云函数,是否部署配置文件中的全部云函数?',
163
+ default: false
164
+ })
165
+
166
+ // 用户不部署全部函数,报错
167
+ if (!isBatch) {
168
+ throw new CloudBaseError(
169
+ '请指定需要部署的云函数的名称或通过 --path 参数指定需要部署的函数的路径!'
170
+ )
171
+ }
172
+ }
173
+
174
+ // 批量部署云函数
175
+ const loading = loadingFactory()
176
+ const tasks = functions.map((func) => async () => {
177
+ loading.start('云函数部署中')
178
+ try {
179
+ await createFunction({
180
+ func,
181
+ envId,
182
+ force,
183
+ codeSecret,
184
+ functionRootPath,
185
+ accessPath: access
186
+ })
187
+ loading.succeed(`[${func.name}] 云函数部署成功`)
188
+ } catch (e) {
189
+ loading.stop()
190
+ await this.handleDeployFail(e, {
191
+ func,
192
+ envId,
193
+ codeSecret,
194
+ functionRootPath,
195
+ accessPath: access
196
+ })
197
+ }
198
+ })
199
+
200
+ if (tasks.length > 5) {
201
+ logger.info('函数数量较多,将使用队列部署')
202
+ }
203
+
204
+ // 控制函数创建并发
205
+ const asyncTaskController = new AsyncTaskParallelController(5, 50)
206
+ asyncTaskController.loadTasks(tasks)
207
+ const results = await asyncTaskController.run()
208
+
209
+ // 输出信息
210
+ const success = results.filter((_) => !_)
211
+ logger.success(`成功部署 ${success?.length} 个函数`)
212
+ // 部署失败
213
+ const err = results.filter((_) => _)
214
+ err?.length && logger.error(`${err?.length} 个云函数部署失败`)
215
+ }
216
+
217
+ async handleDeployFail(e: CloudBaseError, options: ICreateFunctionOptions) {
218
+ const { envId, codeSecret, functionRootPath, func, functionPath, accessPath } = options
219
+ const loading = loadingFactory()
220
+
221
+ if (e.code === 'ResourceInUse.FunctionName' || e.code === 'ResourceInUse.Function') {
222
+ const { force } = await inquirer.prompt({
223
+ type: 'confirm',
224
+ name: 'force',
225
+ message: `存在同名云函数:[${func.name}],是否覆盖原函数代码与配置`,
226
+ default: false
227
+ })
228
+
229
+ if (force) {
230
+ loading.start('云函数部署中...')
231
+ try {
232
+ await createFunction({
233
+ func,
234
+ envId,
235
+ codeSecret,
236
+ accessPath,
237
+ force: true,
238
+ functionPath,
239
+ functionRootPath
240
+ })
241
+ loading.succeed(`[${func.name}] 云函数部署成功!`)
242
+ // await genApiGateway(envId, name)
243
+ await this.printSuccessTips(envId)
244
+ } catch (e) {
245
+ loading.stop()
246
+ throw e
247
+ }
248
+ return
249
+ }
250
+ }
251
+
252
+ throw e
253
+ }
254
+
255
+ @InjectParams()
256
+ async printSuccessTips(envId: string, @Log() log?: Logger) {
257
+ let url = `https://console.cloud.tencent.com/tcb/scf?envId=${envId}`
258
+ const region = await getRegion()
259
+ url += `&rid=${regionIdMap[region]}`
260
+ const link = genClickableLink(url)
261
+ log.breakLine()
262
+ log.info(`控制台查看函数详情或创建HTTP 访问服务链接 🔗:${link}`)
263
+ log.info(`使用 ${highlightCommand('cloudbase functions:list')} 命令查看已部署云函数`)
264
+ }
265
+
266
+ // 创建函数 API 网关
267
+ async genApiGateway(envId: string, name: string) {
268
+ const loading = loadingFactory()
269
+ // 检查是否绑定了 HTTP 网关
270
+ const res = await queryGateway({
271
+ name,
272
+ envId
273
+ })
274
+ // 未开启,不生成 HTTP 调用了链接
275
+ if (res?.EnableService === false) return
276
+ loading.start('生成云函数HTTP 访问服务中...')
277
+
278
+ let path
279
+ if (res?.APISet?.length > 0) {
280
+ path = res.APISet[0]?.Path
281
+ } else {
282
+ path = `/${random(12)}`
283
+ await createGateway({
284
+ envId,
285
+ name,
286
+ path
287
+ })
288
+ }
289
+ loading.stop()
290
+ const link = genClickableLink(`https://${envId}.service.tcloudbase.com${path}`)
291
+ console.log(`\n云函数HTTP 访问服务链接:${link}`)
292
+ }
293
+ }