@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,76 +1,76 @@
1
- import inquirer from 'inquirer'
2
- import { Command, ICommand } from '../common'
3
- import { CloudBaseError } from '../../error'
4
- import { InjectParams, CmdContext, ArgsParams, Log, Logger } from '../../decorators'
5
- import { batchUpdateFunctionConfig, updateFunctionConfig } from '../../function'
6
-
7
- @ICommand()
8
- export class ConfigUpdate extends Command {
9
- get options() {
10
- return {
11
- cmd: 'fn',
12
- childCmd: {
13
- cmd: 'config',
14
- desc: '函数配置管理'
15
- },
16
- childSubCmd: 'update [name]',
17
- deprecateCmd: 'functions:config:update [name]',
18
- options: [
19
- {
20
- flags: '-e, --envId <envId>',
21
- desc: '环境 Id'
22
- }
23
- ],
24
- desc: '更新云函数配置'
25
- }
26
- }
27
-
28
- @InjectParams()
29
- async execute(@CmdContext() ctx, @ArgsParams() params, @Log() log: Logger) {
30
- const {
31
- envId,
32
- config: { functions }
33
- } = ctx
34
- const name = params?.[0]
35
- let isBathUpdate = false
36
-
37
- // 不指定云函数名称,更新配置文件中所有函数的配置
38
- if (!name) {
39
- const { isBatch } = await inquirer.prompt({
40
- type: 'confirm',
41
- name: 'isBatch',
42
- message: '无云函数名称,是否需要更新配置文件中的【全部云函数】的配置?',
43
- default: false
44
- })
45
-
46
- isBathUpdate = isBatch
47
-
48
- if (!isBathUpdate) {
49
- throw new CloudBaseError('请指定云函数名称!')
50
- }
51
- }
52
-
53
- if (isBathUpdate) {
54
- await batchUpdateFunctionConfig({
55
- envId,
56
- functions,
57
- log: true
58
- })
59
- return
60
- }
61
-
62
- const functionItem = functions.find((item) => item.name === name)
63
-
64
- if (!functionItem) {
65
- throw new CloudBaseError('未找到相关函数配置,请检查函数名是否正确')
66
- }
67
-
68
- await updateFunctionConfig({
69
- envId,
70
- functionName: name,
71
- config: functionItem
72
- })
73
-
74
- log.success(`[${name}] 更新云函数配置成功!`)
75
- }
76
- }
1
+ import inquirer from 'inquirer'
2
+ import { Command, ICommand } from '../common'
3
+ import { CloudBaseError } from '../../error'
4
+ import { InjectParams, CmdContext, ArgsParams, Log, Logger } from '../../decorators'
5
+ import { batchUpdateFunctionConfig, updateFunctionConfig } from '../../function'
6
+
7
+ @ICommand()
8
+ export class ConfigUpdate extends Command {
9
+ get options() {
10
+ return {
11
+ cmd: 'fn',
12
+ childCmd: {
13
+ cmd: 'config',
14
+ desc: '函数配置管理'
15
+ },
16
+ childSubCmd: 'update [name]',
17
+ deprecateCmd: 'functions:config:update [name]',
18
+ options: [
19
+ {
20
+ flags: '-e, --envId <envId>',
21
+ desc: '环境 Id'
22
+ }
23
+ ],
24
+ desc: '更新云函数配置'
25
+ }
26
+ }
27
+
28
+ @InjectParams()
29
+ async execute(@CmdContext() ctx, @ArgsParams() params, @Log() log: Logger) {
30
+ const {
31
+ envId,
32
+ config: { functions }
33
+ } = ctx
34
+ const name = params?.[0]
35
+ let isBathUpdate = false
36
+
37
+ // 不指定云函数名称,更新配置文件中所有函数的配置
38
+ if (!name) {
39
+ const { isBatch } = await inquirer.prompt({
40
+ type: 'confirm',
41
+ name: 'isBatch',
42
+ message: '无云函数名称,是否需要更新配置文件中的【全部云函数】的配置?',
43
+ default: false
44
+ })
45
+
46
+ isBathUpdate = isBatch
47
+
48
+ if (!isBathUpdate) {
49
+ throw new CloudBaseError('请指定云函数名称!')
50
+ }
51
+ }
52
+
53
+ if (isBathUpdate) {
54
+ await batchUpdateFunctionConfig({
55
+ envId,
56
+ functions,
57
+ log: true
58
+ })
59
+ return
60
+ }
61
+
62
+ const functionItem = functions.find((item) => item.name === name)
63
+
64
+ if (!functionItem) {
65
+ throw new CloudBaseError('未找到相关函数配置,请检查函数名是否正确')
66
+ }
67
+
68
+ await updateFunctionConfig({
69
+ envId,
70
+ functionName: name,
71
+ config: functionItem
72
+ })
73
+
74
+ log.success(`[${name}] 更新云函数配置成功!`)
75
+ }
76
+ }
@@ -1,62 +1,62 @@
1
- import { Command, ICommand } from '../common'
2
- import { CloudBaseError } from '../../error'
3
- import { copyFunction } from '../../function'
4
- import { InjectParams, EnvId, ArgsOptions, ArgsParams, Log, Logger } from '../../decorators'
5
-
6
- @ICommand()
7
- export class FunctionCopy extends Command {
8
- get options() {
9
- return {
10
- cmd: 'fn',
11
- childCmd: 'copy <name> [newFunctionName]',
12
- deprecateCmd: 'functions:copy <name> [newFunctionName]',
13
- options: [
14
- {
15
- flags: '-e, --envId <envId>',
16
- desc: '环境 Id'
17
- },
18
- {
19
- flags: '-t, --target <targetEnvId>',
20
- desc: '目标环境 Id'
21
- },
22
- // {
23
- // flags: '--code-secret <codeSecret>',
24
- // desc: '代码加密的函数的 CodeSecret'
25
- // },
26
- {
27
- flags: '--force',
28
- desc: '如果目标环境下存在同名函数,覆盖原函数'
29
- }
30
- ],
31
- desc: '拷贝云函数'
32
- }
33
- }
34
-
35
- @InjectParams()
36
- async execute(
37
- @EnvId() envId,
38
- @ArgsOptions() options,
39
- @ArgsParams() params,
40
- @Log() log: Logger
41
- ) {
42
- const name = params?.[0]
43
- const newFunctionName = params?.[1]
44
-
45
- const { force, codeSecret, targetEnvId } = options
46
-
47
- if (!name) {
48
- throw new CloudBaseError('请指定函数名称!')
49
- }
50
-
51
- await copyFunction({
52
- force,
53
- envId,
54
- codeSecret,
55
- functionName: name,
56
- newFunctionName: newFunctionName || name,
57
- targetEnvId: targetEnvId || envId
58
- })
59
-
60
- log.success('拷贝函数成功')
61
- }
62
- }
1
+ import { Command, ICommand } from '../common'
2
+ import { CloudBaseError } from '../../error'
3
+ import { copyFunction } from '../../function'
4
+ import { InjectParams, EnvId, ArgsOptions, ArgsParams, Log, Logger } from '../../decorators'
5
+
6
+ @ICommand()
7
+ export class FunctionCopy extends Command {
8
+ get options() {
9
+ return {
10
+ cmd: 'fn',
11
+ childCmd: 'copy <name> [newFunctionName]',
12
+ deprecateCmd: 'functions:copy <name> [newFunctionName]',
13
+ options: [
14
+ {
15
+ flags: '-e, --envId <envId>',
16
+ desc: '环境 Id'
17
+ },
18
+ {
19
+ flags: '-t, --target <targetEnvId>',
20
+ desc: '目标环境 Id'
21
+ },
22
+ // {
23
+ // flags: '--code-secret <codeSecret>',
24
+ // desc: '代码加密的函数的 CodeSecret'
25
+ // },
26
+ {
27
+ flags: '--force',
28
+ desc: '如果目标环境下存在同名函数,覆盖原函数'
29
+ }
30
+ ],
31
+ desc: '拷贝云函数'
32
+ }
33
+ }
34
+
35
+ @InjectParams()
36
+ async execute(
37
+ @EnvId() envId,
38
+ @ArgsOptions() options,
39
+ @ArgsParams() params,
40
+ @Log() log: Logger
41
+ ) {
42
+ const name = params?.[0]
43
+ const newFunctionName = params?.[1]
44
+
45
+ const { force, codeSecret, targetEnvId } = options
46
+
47
+ if (!name) {
48
+ throw new CloudBaseError('请指定函数名称!')
49
+ }
50
+
51
+ await copyFunction({
52
+ force,
53
+ envId,
54
+ codeSecret,
55
+ functionName: name,
56
+ newFunctionName: newFunctionName || name,
57
+ targetEnvId: targetEnvId || envId
58
+ })
59
+
60
+ log.success('拷贝函数成功')
61
+ }
62
+ }
@@ -1,79 +1,79 @@
1
- import inquirer from 'inquirer'
2
-
3
- import { Command, ICommand } from '../common'
4
- import { CloudBaseError } from '../../error'
5
- import { loadingFactory } from '../../utils'
6
- import { deleteFunction, batchDeleteFunctions } from '../../function'
7
- import { InjectParams, CmdContext, ArgsParams } from '../../decorators'
8
-
9
- @ICommand()
10
- export class DeleteFunction extends Command {
11
- get options() {
12
- return {
13
- cmd: 'fn',
14
- childCmd: 'delete [name]',
15
- deprecateCmd: 'functions:delete [name]',
16
- options: [
17
- {
18
- flags: '-e, --envId <envId>',
19
- desc: '环境 Id'
20
- }
21
- ],
22
- desc: '删除云函数'
23
- }
24
- }
25
-
26
- @InjectParams()
27
- async execute(@CmdContext() ctx, @ArgsParams() params) {
28
- const name = params?.[0]
29
- const {
30
- envId,
31
- config: { functions }
32
- } = ctx
33
-
34
- let isBatchDelete = false
35
-
36
- // 不指定云函数名称,默认删除所有函数
37
- if (!name) {
38
- const answer = await inquirer.prompt({
39
- type: 'confirm',
40
- name: 'isBatch',
41
- message: '无云函数名称,是否需要删除配置文件中的全部云函数?',
42
- default: false
43
- })
44
-
45
- // 危险操作,再次确认
46
- if (answer.isBatch) {
47
- const { reConfirm } = await inquirer.prompt({
48
- type: 'confirm',
49
- name: 'reConfirm',
50
- message: '确定要删除配置文件中的全部云函数?',
51
- default: false
52
- })
53
- isBatchDelete = reConfirm
54
- }
55
-
56
- if (!isBatchDelete) {
57
- throw new CloudBaseError('请指定需要删除的云函数名称!')
58
- }
59
- }
60
-
61
- if (isBatchDelete) {
62
- const names: string[] = functions.map((item) => item.name)
63
- return batchDeleteFunctions({
64
- names,
65
- envId
66
- })
67
- }
68
-
69
- const loading = loadingFactory()
70
- loading.start(`删除函数 [${name}] 中...`)
71
-
72
- await deleteFunction({
73
- envId,
74
- functionName: name
75
- })
76
-
77
- loading.succeed(`删除函数 [${name}] 成功!`)
78
- }
79
- }
1
+ import inquirer from 'inquirer'
2
+
3
+ import { Command, ICommand } from '../common'
4
+ import { CloudBaseError } from '../../error'
5
+ import { loadingFactory } from '../../utils'
6
+ import { deleteFunction, batchDeleteFunctions } from '../../function'
7
+ import { InjectParams, CmdContext, ArgsParams } from '../../decorators'
8
+
9
+ @ICommand()
10
+ export class DeleteFunction extends Command {
11
+ get options() {
12
+ return {
13
+ cmd: 'fn',
14
+ childCmd: 'delete [name]',
15
+ deprecateCmd: 'functions:delete [name]',
16
+ options: [
17
+ {
18
+ flags: '-e, --envId <envId>',
19
+ desc: '环境 Id'
20
+ }
21
+ ],
22
+ desc: '删除云函数'
23
+ }
24
+ }
25
+
26
+ @InjectParams()
27
+ async execute(@CmdContext() ctx, @ArgsParams() params) {
28
+ const name = params?.[0]
29
+ const {
30
+ envId,
31
+ config: { functions }
32
+ } = ctx
33
+
34
+ let isBatchDelete = false
35
+
36
+ // 不指定云函数名称,默认删除所有函数
37
+ if (!name) {
38
+ const answer = await inquirer.prompt({
39
+ type: 'confirm',
40
+ name: 'isBatch',
41
+ message: '无云函数名称,是否需要删除配置文件中的全部云函数?',
42
+ default: false
43
+ })
44
+
45
+ // 危险操作,再次确认
46
+ if (answer.isBatch) {
47
+ const { reConfirm } = await inquirer.prompt({
48
+ type: 'confirm',
49
+ name: 'reConfirm',
50
+ message: '确定要删除配置文件中的全部云函数?',
51
+ default: false
52
+ })
53
+ isBatchDelete = reConfirm
54
+ }
55
+
56
+ if (!isBatchDelete) {
57
+ throw new CloudBaseError('请指定需要删除的云函数名称!')
58
+ }
59
+ }
60
+
61
+ if (isBatchDelete) {
62
+ const names: string[] = functions.map((item) => item.name)
63
+ return batchDeleteFunctions({
64
+ names,
65
+ envId
66
+ })
67
+ }
68
+
69
+ const loading = loadingFactory()
70
+ loading.start(`删除函数 [${name}] 中...`)
71
+
72
+ await deleteFunction({
73
+ envId,
74
+ functionName: name
75
+ })
76
+
77
+ loading.succeed(`删除函数 [${name}] 成功!`)
78
+ }
79
+ }