clever-tools 4.4.1 → 4.5.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 (291) hide show
  1. package/bin/clever.js +208 -2125
  2. package/package.json +33 -25
  3. package/src/commands/README.md +65 -0
  4. package/src/commands/accesslogs/accesslogs.command.js +158 -0
  5. package/src/commands/accesslogs/accesslogs.docs.md +20 -0
  6. package/src/commands/{activity.js → activity/activity.command.js} +74 -44
  7. package/src/commands/activity/activity.docs.md +19 -0
  8. package/src/commands/addon/addon.args.js +14 -0
  9. package/src/commands/addon/addon.command.js +7 -0
  10. package/src/commands/addon/addon.create.command.js +236 -0
  11. package/src/commands/addon/addon.delete.command.js +32 -0
  12. package/src/commands/addon/addon.docs.md +156 -0
  13. package/src/commands/addon/addon.env.command.js +50 -0
  14. package/src/commands/addon/addon.list.command.js +55 -0
  15. package/src/commands/addon/addon.providers.command.js +45 -0
  16. package/src/commands/addon/addon.providers.show.command.js +99 -0
  17. package/src/commands/addon/addon.rename.command.js +24 -0
  18. package/src/commands/applications/applications.command.js +59 -0
  19. package/src/commands/applications/applications.docs.md +31 -0
  20. package/src/commands/applications/applications.list.command.js +100 -0
  21. package/src/commands/cancel-deploy/cancel-deploy.command.js +30 -0
  22. package/src/commands/cancel-deploy/cancel-deploy.docs.md +16 -0
  23. package/src/commands/config/config.args.js +10 -0
  24. package/src/commands/config/config.command.js +20 -0
  25. package/src/commands/config/config.docs.md +86 -0
  26. package/src/commands/config/config.get.command.js +21 -0
  27. package/src/commands/config/config.set.command.js +38 -0
  28. package/src/commands/config/config.update.command.js +88 -0
  29. package/src/commands/console/console.command.js +31 -0
  30. package/src/commands/console/console.docs.md +16 -0
  31. package/src/commands/create/create.command.js +173 -0
  32. package/src/commands/create/create.docs.md +27 -0
  33. package/src/commands/{curl.js → curl/curl.command.js} +10 -3
  34. package/src/commands/curl/curl.docs.md +9 -0
  35. package/src/commands/database/database.args.js +8 -0
  36. package/src/commands/database/database.backups.command.js +60 -0
  37. package/src/commands/database/database.backups.download.command.js +55 -0
  38. package/src/commands/database/database.command.js +10 -0
  39. package/src/commands/database/database.docs.md +52 -0
  40. package/src/commands/delete/delete.command.js +43 -0
  41. package/src/commands/delete/delete.docs.md +17 -0
  42. package/src/commands/deploy/deploy.command.js +166 -0
  43. package/src/commands/deploy/deploy.docs.md +22 -0
  44. package/src/commands/diag/diag.command.js +136 -0
  45. package/src/commands/diag/diag.docs.md +15 -0
  46. package/src/commands/domain/domain.add.command.js +25 -0
  47. package/src/commands/domain/domain.args.js +8 -0
  48. package/src/commands/domain/domain.command.js +38 -0
  49. package/src/commands/domain/domain.diag.command.js +204 -0
  50. package/src/commands/domain/domain.docs.md +143 -0
  51. package/src/commands/domain/domain.favourite.command.js +35 -0
  52. package/src/commands/domain/domain.favourite.set.command.js +24 -0
  53. package/src/commands/domain/domain.favourite.unset.command.js +23 -0
  54. package/src/commands/domain/domain.overview.command.js +157 -0
  55. package/src/commands/domain/domain.rm.command.js +25 -0
  56. package/src/commands/drain/drain.args.js +8 -0
  57. package/src/commands/drain/drain.command.js +56 -0
  58. package/src/commands/drain/drain.create.command.js +128 -0
  59. package/src/commands/drain/drain.disable.command.js +27 -0
  60. package/src/commands/drain/drain.docs.md +129 -0
  61. package/src/commands/drain/drain.enable.command.js +27 -0
  62. package/src/commands/drain/drain.get.command.js +38 -0
  63. package/src/commands/drain/drain.remove.command.js +26 -0
  64. package/src/commands/emails/emails.add.command.js +32 -0
  65. package/src/commands/emails/emails.args.js +8 -0
  66. package/src/commands/emails/emails.command.js +35 -0
  67. package/src/commands/emails/emails.docs.md +79 -0
  68. package/src/commands/emails/emails.open.command.js +15 -0
  69. package/src/commands/emails/emails.primary.command.js +29 -0
  70. package/src/commands/emails/emails.remove-all.command.js +54 -0
  71. package/src/commands/emails/emails.remove.command.js +25 -0
  72. package/src/commands/env/env.command.js +77 -0
  73. package/src/commands/env/env.docs.md +99 -0
  74. package/src/commands/env/env.import-vars.command.js +45 -0
  75. package/src/commands/env/env.import.command.js +29 -0
  76. package/src/commands/env/env.rm.command.js +25 -0
  77. package/src/commands/env/env.set.command.js +32 -0
  78. package/src/commands/features/features.args.js +9 -0
  79. package/src/commands/features/features.command.js +7 -0
  80. package/src/commands/features/features.disable.command.js +25 -0
  81. package/src/commands/features/features.docs.md +71 -0
  82. package/src/commands/features/features.enable.command.js +32 -0
  83. package/src/commands/features/features.info.command.js +27 -0
  84. package/src/commands/features/features.list.command.js +49 -0
  85. package/src/commands/global.args.js +45 -0
  86. package/src/commands/global.commands.js +461 -0
  87. package/src/commands/global.options.js +186 -0
  88. package/src/commands/help/help.command.js +9 -0
  89. package/src/commands/help/help.docs.md +9 -0
  90. package/src/commands/k8s/k8s.add-persistent-storage.command.js +39 -0
  91. package/src/commands/k8s/k8s.args.js +9 -0
  92. package/src/commands/k8s/k8s.command.js +12 -0
  93. package/src/commands/k8s/k8s.create.command.js +86 -0
  94. package/src/commands/k8s/k8s.delete.command.js +40 -0
  95. package/src/commands/k8s/k8s.docs.md +131 -0
  96. package/src/commands/k8s/k8s.get-kubeconfig.command.js +32 -0
  97. package/src/commands/k8s/k8s.get.command.js +43 -0
  98. package/src/commands/k8s/k8s.list.command.js +38 -0
  99. package/src/commands/keycloak/keycloak.command.js +17 -0
  100. package/src/commands/keycloak/keycloak.disable-ng.command.js +13 -0
  101. package/src/commands/keycloak/keycloak.docs.md +197 -0
  102. package/src/commands/keycloak/keycloak.enable-ng.command.js +13 -0
  103. package/src/commands/keycloak/keycloak.get.command.js +17 -0
  104. package/src/commands/keycloak/keycloak.open.command.js +13 -0
  105. package/src/commands/keycloak/keycloak.open.logs.command.js +13 -0
  106. package/src/commands/keycloak/keycloak.open.webui.command.js +13 -0
  107. package/src/commands/keycloak/keycloak.rebuild.command.js +13 -0
  108. package/src/commands/keycloak/keycloak.restart.command.js +13 -0
  109. package/src/commands/keycloak/keycloak.version.check.command.js +17 -0
  110. package/src/commands/keycloak/keycloak.version.command.js +17 -0
  111. package/src/commands/keycloak/keycloak.version.update.command.js +17 -0
  112. package/src/commands/kv/kv.command.js +99 -0
  113. package/src/commands/kv/kv.docs.md +27 -0
  114. package/src/commands/link/link.command.js +31 -0
  115. package/src/commands/link/link.docs.md +22 -0
  116. package/src/commands/{login.js → login/login.command.js} +44 -22
  117. package/src/commands/login/login.docs.md +16 -0
  118. package/src/commands/logout/logout.command.js +15 -0
  119. package/src/commands/logout/logout.docs.md +9 -0
  120. package/src/commands/logs/logs.command.js +81 -0
  121. package/src/commands/logs/logs.docs.md +22 -0
  122. package/src/commands/make-default/make-default.command.js +17 -0
  123. package/src/commands/make-default/make-default.docs.md +15 -0
  124. package/src/commands/matomo/matomo.command.js +17 -0
  125. package/src/commands/matomo/matomo.docs.md +109 -0
  126. package/src/commands/matomo/matomo.get.command.js +17 -0
  127. package/src/commands/matomo/matomo.open.command.js +13 -0
  128. package/src/commands/matomo/matomo.open.logs.command.js +13 -0
  129. package/src/commands/matomo/matomo.open.webui.command.js +13 -0
  130. package/src/commands/matomo/matomo.rebuild.command.js +13 -0
  131. package/src/commands/matomo/matomo.restart.command.js +13 -0
  132. package/src/commands/metabase/metabase.command.js +17 -0
  133. package/src/commands/metabase/metabase.docs.md +169 -0
  134. package/src/commands/metabase/metabase.get.command.js +17 -0
  135. package/src/commands/metabase/metabase.open.command.js +13 -0
  136. package/src/commands/metabase/metabase.open.logs.command.js +13 -0
  137. package/src/commands/metabase/metabase.open.webui.command.js +13 -0
  138. package/src/commands/metabase/metabase.rebuild.command.js +13 -0
  139. package/src/commands/metabase/metabase.restart.command.js +13 -0
  140. package/src/commands/metabase/metabase.version.check.command.js +17 -0
  141. package/src/commands/metabase/metabase.version.command.js +17 -0
  142. package/src/commands/metabase/metabase.version.update.command.js +17 -0
  143. package/src/commands/ng/ng.args.js +27 -0
  144. package/src/commands/ng/ng.command.js +45 -0
  145. package/src/commands/ng/ng.create.command.js +60 -0
  146. package/src/commands/ng/ng.create.external.command.js +44 -0
  147. package/src/commands/ng/ng.delete.command.js +22 -0
  148. package/src/commands/ng/ng.delete.external.command.js +25 -0
  149. package/src/commands/ng/ng.docs.md +214 -0
  150. package/src/commands/ng/ng.get-config.command.js +32 -0
  151. package/src/commands/ng/ng.get.command.js +22 -0
  152. package/src/commands/ng/ng.link.command.js +25 -0
  153. package/src/commands/ng/ng.options.js +9 -0
  154. package/src/commands/ng/ng.search.command.js +22 -0
  155. package/src/commands/ng/ng.unlink.command.js +25 -0
  156. package/src/commands/notify-email/notify-email.add.command.js +65 -0
  157. package/src/commands/notify-email/notify-email.command.js +61 -0
  158. package/src/commands/notify-email/notify-email.docs.md +60 -0
  159. package/src/commands/notify-email/notify-email.remove.command.js +24 -0
  160. package/src/commands/open/open.command.js +24 -0
  161. package/src/commands/open/open.docs.md +16 -0
  162. package/src/commands/otoroshi/otoroshi.command.js +17 -0
  163. package/src/commands/otoroshi/otoroshi.disable-ng.command.js +13 -0
  164. package/src/commands/otoroshi/otoroshi.docs.md +211 -0
  165. package/src/commands/otoroshi/otoroshi.enable-ng.command.js +13 -0
  166. package/src/commands/otoroshi/otoroshi.get-config.command.js +13 -0
  167. package/src/commands/otoroshi/otoroshi.get.command.js +17 -0
  168. package/src/commands/otoroshi/otoroshi.open.command.js +13 -0
  169. package/src/commands/otoroshi/otoroshi.open.logs.command.js +13 -0
  170. package/src/commands/otoroshi/otoroshi.open.webui.command.js +13 -0
  171. package/src/commands/otoroshi/otoroshi.rebuild.command.js +13 -0
  172. package/src/commands/otoroshi/otoroshi.restart.command.js +13 -0
  173. package/src/commands/otoroshi/otoroshi.version.check.command.js +17 -0
  174. package/src/commands/otoroshi/otoroshi.version.command.js +17 -0
  175. package/src/commands/otoroshi/otoroshi.version.update.command.js +17 -0
  176. package/src/commands/profile/profile.command.js +60 -0
  177. package/src/commands/profile/profile.docs.md +23 -0
  178. package/src/commands/profile/profile.open.command.js +12 -0
  179. package/src/commands/published-config/published-config.command.js +40 -0
  180. package/src/commands/published-config/published-config.docs.md +77 -0
  181. package/src/commands/published-config/published-config.import.command.js +29 -0
  182. package/src/commands/published-config/published-config.rm.command.js +27 -0
  183. package/src/commands/published-config/published-config.set.command.js +34 -0
  184. package/src/commands/restart/restart.command.js +77 -0
  185. package/src/commands/restart/restart.docs.md +21 -0
  186. package/src/commands/scale/scale.command.js +121 -0
  187. package/src/commands/scale/scale.docs.md +23 -0
  188. package/src/commands/service/service.command.js +91 -0
  189. package/src/commands/service/service.docs.md +104 -0
  190. package/src/commands/service/service.link-addon.command.js +24 -0
  191. package/src/commands/service/service.link-app.command.js +23 -0
  192. package/src/commands/service/service.unlink-addon.command.js +24 -0
  193. package/src/commands/service/service.unlink-app.command.js +23 -0
  194. package/src/commands/ssh/ssh.command.js +40 -0
  195. package/src/commands/ssh/ssh.docs.md +17 -0
  196. package/src/commands/ssh-keys/ssh-keys.add.command.js +41 -0
  197. package/src/commands/ssh-keys/ssh-keys.args.js +8 -0
  198. package/src/commands/ssh-keys/ssh-keys.command.js +50 -0
  199. package/src/commands/ssh-keys/ssh-keys.docs.md +66 -0
  200. package/src/commands/ssh-keys/ssh-keys.open.command.js +12 -0
  201. package/src/commands/ssh-keys/ssh-keys.remove-all.command.js +54 -0
  202. package/src/commands/ssh-keys/ssh-keys.remove.command.js +26 -0
  203. package/src/commands/status/status.command.js +122 -0
  204. package/src/commands/status/status.docs.md +17 -0
  205. package/src/commands/stop/stop.command.js +23 -0
  206. package/src/commands/stop/stop.docs.md +16 -0
  207. package/src/commands/tcp-redirs/tcp-redirs.add.command.js +24 -0
  208. package/src/commands/tcp-redirs/tcp-redirs.command.js +41 -0
  209. package/src/commands/tcp-redirs/tcp-redirs.docs.md +71 -0
  210. package/src/commands/tcp-redirs/tcp-redirs.list-namespaces.command.js +48 -0
  211. package/src/commands/tcp-redirs/tcp-redirs.options.js +11 -0
  212. package/src/commands/tcp-redirs/tcp-redirs.remove.command.js +34 -0
  213. package/src/commands/tokens/tokens.command.js +43 -0
  214. package/src/commands/tokens/tokens.create.command.js +108 -0
  215. package/src/commands/tokens/tokens.docs.md +50 -0
  216. package/src/commands/tokens/tokens.revoke.command.js +25 -0
  217. package/src/commands/unlink/unlink.command.js +21 -0
  218. package/src/commands/unlink/unlink.docs.md +15 -0
  219. package/src/commands/version/version.command.js +13 -0
  220. package/src/commands/version/version.docs.md +9 -0
  221. package/src/commands/webhooks/webhooks.add.command.js +51 -0
  222. package/src/commands/webhooks/webhooks.command.js +57 -0
  223. package/src/commands/webhooks/webhooks.docs.md +61 -0
  224. package/src/commands/webhooks/webhooks.remove.command.js +24 -0
  225. package/src/lib/cliparse-patched.js +192 -0
  226. package/src/lib/define-argument.js +7 -0
  227. package/src/lib/define-argument.types.d.ts +23 -0
  228. package/src/lib/define-command.js +7 -0
  229. package/src/lib/define-command.types.d.ts +85 -0
  230. package/src/lib/define-common.types.d.ts +18 -0
  231. package/src/lib/define-option.js +7 -0
  232. package/src/lib/define-option.types.d.ts +29 -0
  233. package/src/lib/get-command-info.js +86 -0
  234. package/src/lib/get-command-info.types.d.ts +42 -0
  235. package/src/lib/zod-utils.js +66 -0
  236. package/src/models/addon.js +2 -3
  237. package/src/models/application.js +4 -5
  238. package/src/models/application_configuration.js +5 -23
  239. package/src/models/domain.js +34 -2
  240. package/src/models/exit-strategy-option.js +0 -9
  241. package/src/models/git.js +1 -4
  242. package/src/models/log-v4.js +5 -0
  243. package/src/models/log.js +5 -0
  244. package/src/models/namespaces.js +1 -2
  245. package/src/models/notification.js +1 -7
  246. package/src/parsers.js +33 -92
  247. package/src/command-options.js +0 -55
  248. package/src/command-promise-handler.js +0 -16
  249. package/src/commands/accesslogs.js +0 -138
  250. package/src/commands/addon.js +0 -391
  251. package/src/commands/applications.js +0 -123
  252. package/src/commands/cancel-deploy.js +0 -19
  253. package/src/commands/config.js +0 -47
  254. package/src/commands/console.js +0 -20
  255. package/src/commands/create.js +0 -129
  256. package/src/commands/database.js +0 -73
  257. package/src/commands/delete.js +0 -24
  258. package/src/commands/deploy.js +0 -133
  259. package/src/commands/diag.js +0 -126
  260. package/src/commands/domain.js +0 -445
  261. package/src/commands/drain.js +0 -164
  262. package/src/commands/emails.js +0 -156
  263. package/src/commands/env.js +0 -124
  264. package/src/commands/features.js +0 -87
  265. package/src/commands/k8s.js +0 -193
  266. package/src/commands/keycloak.js +0 -138
  267. package/src/commands/kv.js +0 -93
  268. package/src/commands/link.js +0 -20
  269. package/src/commands/logout.js +0 -8
  270. package/src/commands/logs.js +0 -45
  271. package/src/commands/makeDefault.js +0 -11
  272. package/src/commands/matomo.js +0 -85
  273. package/src/commands/metabase.js +0 -112
  274. package/src/commands/ng.js +0 -202
  275. package/src/commands/notify-email.js +0 -99
  276. package/src/commands/open.js +0 -13
  277. package/src/commands/otoroshi.js +0 -149
  278. package/src/commands/profile.js +0 -55
  279. package/src/commands/published-config.js +0 -70
  280. package/src/commands/restart.js +0 -52
  281. package/src/commands/scale.js +0 -66
  282. package/src/commands/service.js +0 -105
  283. package/src/commands/ssh-keys.js +0 -144
  284. package/src/commands/ssh.js +0 -20
  285. package/src/commands/status.js +0 -115
  286. package/src/commands/stop.js +0 -12
  287. package/src/commands/tcp-redirs.js +0 -80
  288. package/src/commands/tokens.js +0 -144
  289. package/src/commands/unlink.js +0 -14
  290. package/src/commands/version.js +0 -6
  291. package/src/commands/webhooks.js +0 -74
@@ -0,0 +1,61 @@
1
+ # 📖 `clever webhooks` command reference
2
+
3
+ ## ➡️ `clever webhooks` <kbd>Since 0.6.0</kbd>
4
+
5
+ Manage webhooks
6
+
7
+ ```bash
8
+ clever webhooks [options]
9
+ ```
10
+
11
+ ### ⚙️ Options
12
+
13
+ |Name|Description|
14
+ |---|---|
15
+ |`-F`, `--format` `<format>`|Output format (human, json) (default: human)|
16
+ |`--list-all`|List all notifications for your user or for an organisation with the '--org' option|
17
+ |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
18
+
19
+ ## ➡️ `clever webhooks add` <kbd>Since 0.6.0</kbd>
20
+
21
+ Register webhook to be called when events happen
22
+
23
+ ```bash
24
+ clever webhooks add <name> <url> [options]
25
+ ```
26
+
27
+ ### 📥 Arguments
28
+
29
+ |Name|Description|
30
+ |---|---|
31
+ |`name`|Notification name|
32
+ |`url`|Webhook URL|
33
+
34
+ ### ⚙️ Options
35
+
36
+ |Name|Description|
37
+ |---|---|
38
+ |`--event` `<event-type>`|Restrict notifications to specific event types|
39
+ |`--format` `<format>`|Format of the body sent to the webhook ('raw', 'slack', 'gitter', or 'flowdock') (default: raw)|
40
+ |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
41
+ |`--service` `<service-id>`|Restrict notifications to specific applications and add-ons|
42
+
43
+ ## ➡️ `clever webhooks remove` <kbd>Since 0.6.0</kbd>
44
+
45
+ Remove an existing webhook
46
+
47
+ ```bash
48
+ clever webhooks remove <notification-id> [options]
49
+ ```
50
+
51
+ ### 📥 Arguments
52
+
53
+ |Name|Description|
54
+ |---|---|
55
+ |`notification-id`|Notification ID|
56
+
57
+ ### ⚙️ Options
58
+
59
+ |Name|Description|
60
+ |---|---|
61
+ |`-o`, `--org`, `--owner` `<org-id\|org-name>`|Organisation to target by its ID (or name, if unambiguous)|
@@ -0,0 +1,24 @@
1
+ import { deleteWebhook } from '@clevercloud/client/esm/api/v2/notification.js';
2
+ import { defineCommand } from '../../lib/define-command.js';
3
+ import { Logger } from '../../logger.js';
4
+ import { getOrgaIdOrUserId } from '../../models/notification.js';
5
+ import { sendToApi } from '../../models/send-to-api.js';
6
+ import { notificationIdArg } from '../global.args.js';
7
+ import { orgaIdOrNameOption } from '../global.options.js';
8
+
9
+ export const webhooksRemoveCommand = defineCommand({
10
+ description: 'Remove an existing webhook',
11
+ since: '0.6.0',
12
+ options: {
13
+ org: orgaIdOrNameOption,
14
+ },
15
+ args: [notificationIdArg],
16
+ async handler(options, notificationId) {
17
+ const { org } = options;
18
+
19
+ const ownerId = await getOrgaIdOrUserId(org);
20
+ await deleteWebhook({ ownerId, id: notificationId }).then(sendToApi);
21
+
22
+ Logger.println('The notification has been successfully removed');
23
+ },
24
+ });
@@ -0,0 +1,192 @@
1
+ import cliparseOriginal from 'cliparse';
2
+ import cliparseCommandModule from 'cliparse/src/command.js';
3
+ import semver from 'semver';
4
+ import pkg from '../../package.json' with { type: 'json' };
5
+ import { Logger } from '../logger.js';
6
+ import { getCommandInfo } from './get-command-info.js';
7
+ import { styleText } from './style-text.js';
8
+
9
+ // Patch cliparse.command so we can catch errors
10
+ const cliparseCommand = cliparseOriginal.command;
11
+ cliparseOriginal.command = function (name, options, commandFunction) {
12
+ if (commandFunction == null) {
13
+ return cliparseCommand(name, options);
14
+ }
15
+
16
+ const command = cliparseCommand(name, options, (params) => {
17
+ const args = params.args ?? [];
18
+ // Map options from cliparse format (using option.name as key, e.g. 'index-prefix')
19
+ // to the original keys from the command definition (e.g. 'indexPrefix')
20
+ const mappedOptions = mapOptionsToDefinitionKeys(params.options, command._definition);
21
+ const promise = commandFunction(mappedOptions, ...args);
22
+ promise.catch((error) => {
23
+ Logger.error(error);
24
+ const semverIsOk = semver.satisfies(process.version, pkg.engines.node);
25
+ if (!semverIsOk) {
26
+ Logger.warn(
27
+ `You are using node ${process.version}, some of our commands require node ${pkg.engines.node}. The error may be caused by this.`,
28
+ );
29
+ }
30
+ process.exit(1);
31
+ });
32
+ });
33
+ return command;
34
+ };
35
+
36
+ /**
37
+ * Map options from cliparse format (using option.name) to the original definition keys.
38
+ * For example, { theOptionName: defineOption({ name: 'the-option-name', ... }) },
39
+ * cliparse will return { 'the-option-name': value }, and we need to convert it to { theOptionName: value }.
40
+ * @param {Record<string, unknown>} options - Options object from cliparse with option.name as keys
41
+ * @param {CommandDefinition} definition - Command definition
42
+ * @returns {Record<string, unknown>} Options object with original definition keys
43
+ */
44
+ function mapOptionsToDefinitionKeys(options, definition) {
45
+ if (!definition?.options) {
46
+ return options;
47
+ }
48
+
49
+ // Build a reverse map: option.name -> definition key
50
+ const nameToKey = new Map();
51
+ for (const [key, optionDef] of Object.entries(definition.options)) {
52
+ nameToKey.set(optionDef.name, key);
53
+ }
54
+
55
+ // Map options to use definition keys
56
+ const mappedOptions = {};
57
+ for (const [name, value] of Object.entries(options)) {
58
+ const key = nameToKey.get(name) ?? name;
59
+ mappedOptions[key] = value;
60
+ }
61
+
62
+ return mappedOptions;
63
+ }
64
+
65
+ /**
66
+ * Patched help function for cliparse commands.
67
+ * Called internally by cliparse when --help is used.
68
+ * Generates formatted help output with usage, arguments, options, and subcommands.
69
+ * @param {Array<{name: string, description: string, commands: Array, _definition: CommandDefinition}>} context - Command context stack
70
+ * @returns {string} Formatted help text
71
+ */
72
+ cliparseCommandModule.help = function (context) {
73
+ const cmd = context.at(-1);
74
+ const path = context.slice(1).map((c) => c.name);
75
+ const commandInfo = getCommandInfo(path, cmd._definition);
76
+
77
+ const allRows = [];
78
+
79
+ let argumentsRows;
80
+ if (commandInfo.args) {
81
+ argumentsRows = commandInfo.args.map((arg) => {
82
+ let description = arg.description;
83
+ if (arg.optional) description += ` ${styleText('dim', arg.optional)}`;
84
+ return [arg.name, description];
85
+ });
86
+ allRows.push(...argumentsRows);
87
+ }
88
+
89
+ let optionsRows;
90
+ if (commandInfo.options) {
91
+ optionsRows = commandInfo.options.map((opt) => {
92
+ const placeholder = opt.placeholder ? ` ${opt.placeholder}` : '';
93
+ const aliasesPadding = opt.aliases[0].length === 2 ? '' : ' ';
94
+ const aliases = aliasesPadding + opt.aliases.join(', ') + placeholder;
95
+ let description = opt.description;
96
+ if (opt.deprecated) description += ` ${styleText('dim', opt.deprecated)}`;
97
+ if (opt.required) description += ` ${styleText('dim', opt.required)}`;
98
+ if (opt.default) description += ` ${styleText('dim', opt.default)}`;
99
+ return [aliases, description];
100
+ });
101
+ allRows.push(...optionsRows);
102
+ }
103
+
104
+ const availableCommandsRows = cmd.commands.map((cmd) => [cmd.name, cmd.description.split('\n')[0]]);
105
+ allRows.push(...availableCommandsRows);
106
+
107
+ const firstColumnWith = Math.max(...allRows.map(([cell]) => cell.length));
108
+
109
+ const parts = [cmd._definition.description];
110
+
111
+ parts.push(formatSection('USAGE', [commandInfo.usage]));
112
+ if (availableCommandsRows.length > 0) {
113
+ parts.push(formatSectionWithColumns('COMMANDS', availableCommandsRows, firstColumnWith));
114
+ }
115
+ if (argumentsRows) {
116
+ parts.push(formatSectionWithColumns('ARGUMENTS', argumentsRows, firstColumnWith));
117
+ }
118
+ if (optionsRows) {
119
+ parts.push(formatSectionWithColumns('OPTIONS', optionsRows, firstColumnWith));
120
+ }
121
+ if (cmd._definition.examples?.length > 0) {
122
+ parts.push(formatSection('EXAMPLES', cmd._definition.examples));
123
+ }
124
+
125
+ return parts.join('\n\n');
126
+ };
127
+
128
+ /**
129
+ * @param {string} title
130
+ * @param {Array<string>} lines
131
+ */
132
+ function formatSection(title, lines) {
133
+ return [styleText('bold', title), ...lines.map((l) => ` ${l}`)].join('\n');
134
+ }
135
+
136
+ /**
137
+ * @param {string} title
138
+ * @param {string[][]} rows
139
+ * @param {number} firstColumnWidth
140
+ */
141
+ function formatSectionWithColumns(title, rows, firstColumnWidth) {
142
+ const lines = rows.map(([firstColumn, otherColumn]) => firstColumn.padEnd(firstColumnWidth + 4, ' ') + otherColumn);
143
+ return formatSection(title, lines);
144
+ }
145
+
146
+ // Wrap parser functions to allow them to simply return values or throw errors
147
+ // instead of using cliparse.parsers.success/error
148
+ function wrapParser(parser) {
149
+ return (value) => {
150
+ try {
151
+ return cliparseOriginal.parsers.success(parser(value));
152
+ } catch (error) {
153
+ return cliparseOriginal.parsers.error(error.message);
154
+ }
155
+ };
156
+ }
157
+
158
+ // Wrap complete functions to allow returning plain arrays
159
+ // instead of cliparse.autocomplete.words(array)
160
+ function wrapComplete(complete) {
161
+ return (word) => {
162
+ // Support both functions and static arrays (e.g. complete: Drain.DRAIN_TYPE_CLI_CODES)
163
+ const result = typeof complete === 'function' ? complete(word) : complete;
164
+ return Promise.resolve(result).then(cliparse.autocomplete.words);
165
+ };
166
+ }
167
+
168
+ // Patch cliparse.option to wrap parser and complete functions
169
+ const cliparseOption = cliparseOriginal.option;
170
+ cliparseOriginal.option = function (name, options) {
171
+ if (options?.parser != null) {
172
+ options.parser = wrapParser(options.parser);
173
+ }
174
+ if (options?.complete != null) {
175
+ options.complete = wrapComplete(options.complete);
176
+ }
177
+ return cliparseOption(name, options);
178
+ };
179
+
180
+ // Patch cliparse.argument to wrap parser and complete functions
181
+ const cliparseArgument = cliparseOriginal.argument;
182
+ cliparseOriginal.argument = function (name, options) {
183
+ if (options?.parser != null) {
184
+ options.parser = wrapParser(options.parser);
185
+ }
186
+ if (options?.complete != null) {
187
+ options.complete = wrapComplete(options.complete);
188
+ }
189
+ return cliparseArgument(name, options);
190
+ };
191
+
192
+ export const cliparse = cliparseOriginal;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Define a CLI argument with full type inference from Zod schema.
3
+ * @type {import('./define-argument.types.js').defineArgument}
4
+ */
5
+ export function defineArgument(argumentDefinition) {
6
+ return argumentDefinition;
7
+ }
@@ -0,0 +1,23 @@
1
+ import { z } from 'zod';
2
+ import { CompletionFunction } from './define-common.types.js';
3
+
4
+ /** Define a CLI argument with full type inference from Zod schema. */
5
+ export function defineArgument<S extends z.ZodType>(definition: ArgumentDefinition<S>): ArgumentDefinition<S>;
6
+
7
+ /** Argument definition shape with Zod schema for type inference. */
8
+ export interface ArgumentDefinition<S extends z.ZodType = z.ZodType> {
9
+ /** Zod schema defining the argument's type, default value, and validation. */
10
+ schema: S;
11
+
12
+ /** Human-readable description for help text. */
13
+ description: string;
14
+
15
+ /** Placeholder text shown in help documentation (e.g., 'addon-id'). */
16
+ placeholder: string;
17
+
18
+ /** Shell completion function. Can be sync or async. */
19
+ complete?: CompletionFunction;
20
+
21
+ /** Mark as deprecated. `true` for generic warning, or a string with migration instructions. */
22
+ deprecated?: boolean | string;
23
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Define a CLI command with full type inference from Zod schemas.
3
+ * @type {import('./define-command.types.js').defineCommand}
4
+ */
5
+ export function defineCommand(definition) {
6
+ return definition;
7
+ }
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+
3
+ import { ArgumentDefinition } from './define-argument.types.js';
4
+ import { OptionDefinition } from './define-option.types.js';
5
+
6
+ /** Define a CLI command with full type inference from option and argument definitions. */
7
+ // The `const` modifier on `A` is critical: it tells TypeScript to infer the exact
8
+ // tuple type (e.g., `[StringArg, NumberArg]`) rather than widening to `ArgumentDefinition[]`.
9
+ // This preserves argument order and types for the handler signature.
10
+ export function defineCommand<O extends OptionsRecord | undefined, const A extends ArgumentsArray | undefined>(
11
+ definition: CommandDefinition<O, A>,
12
+ ): CommandDefinition<O, A>;
13
+
14
+ /**
15
+ * Full specification for a CLI command.
16
+ * @template O - Options record type, inferred from the `options` property.
17
+ * @template A - Arguments tuple type, inferred from the `args` property.
18
+ */
19
+ // Generic parameters allow TypeScript to infer exact types for options and arguments,
20
+ // which then flow into the handler signature for full type safety.
21
+ // Some commands don't have options, some don't have arguments, some don't have both.
22
+ export interface CommandDefinition<
23
+ O extends OptionsRecord | undefined = OptionsRecord,
24
+ A extends ArgumentsArray | undefined = ArgumentsArray,
25
+ > {
26
+ /** Short description for help text. */
27
+ description: string;
28
+
29
+ /** Usage examples shown in help output. */
30
+ examples?: string[];
31
+
32
+ /**
33
+ * Mark command as experimental.
34
+ * Experimental commands may show a warning when used.
35
+ */
36
+ isExperimental?: boolean;
37
+
38
+ /**
39
+ * Feature flag name that must be enabled for this command to be available.
40
+ * If the feature flag is not enabled, the command will be hidden.
41
+ */
42
+ featureFlag?: string;
43
+
44
+ /** Version when this command was introduced (semver format, e.g., '2.1.0'). */
45
+ since?: `${number}.${number}.${number}`;
46
+
47
+ /** Options (named options like --type, --region, --format). */
48
+ options?: O;
49
+
50
+ /** Positional arguments, passed to the handler as individual parameters in order. */
51
+ args?: A;
52
+
53
+ /** Command handler. Receives parsed options, then args. Null for parent-only commands. */
54
+ handler: CommandHandler<O, A> | null;
55
+ }
56
+
57
+ // Dictionary of named options (e.g., { format: OptionDefinition, region: OptionDefinition }).
58
+ type OptionsRecord = Record<string, OptionDefinition>;
59
+
60
+ // Tuple of positional arguments.
61
+ // Must be `readonly` to preserve tuple structure and allow `const` inference.
62
+ type ArgumentsArray = readonly ArgumentDefinition[];
63
+
64
+ // Handler signature adapts based on whether args are defined.
65
+ // - With args: `(options, ...args) => Promise<void>` - args spread as individual parameters.
66
+ // - Without args: `(options) => Promise<void>` - no extra parameters.
67
+ type CommandHandler<O, A> = A extends ArgumentsArray
68
+ ? (options: InferOptionsType<O>, ...args: InferArgsType<A>) => Promise<void>
69
+ : (options: InferOptionsType<O>) => Promise<void>;
70
+
71
+ // Extracts runtime types from option definitions using Zod inference.
72
+ // Maps `{ foo: { schema: z.string() } }` → `{ foo: string }`.
73
+ type InferOptionsType<O> = O extends OptionsRecord
74
+ ? { [K in keyof O]: z.infer<O[K]['schema']> }
75
+ : Record<string, never>;
76
+
77
+ // Extracts runtime types from argument definitions as a tuple.
78
+ // Maps `[{ schema: z.string() }, { schema: z.number() }]` → `[string, number]`.
79
+ // Preserves tuple order so args are passed to handlers in the correct position.
80
+ // `keyof A` on an array includes both numeric indices ("0", "1", ...) and
81
+ // array properties ("length", "push", etc.). The `extends ArgumentDefinition`
82
+ // check returns `never` for non-index keys, effectively filtering them out.
83
+ type InferArgsType<A extends ArgumentsArray> = {
84
+ [K in keyof A]: A[K] extends ArgumentDefinition ? z.infer<A[K]['schema']> : never;
85
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Completion function signature for shell autocompletion.
3
+ * Can be sync or async for API-based completions.
4
+ */
5
+ export type CompletionFunction = (context?: CompletionContext) => string[] | Promise<string[]>;
6
+
7
+ /**
8
+ * Completion context provided to completion functions.
9
+ * Contains partial command state for intelligent completion.
10
+ */
11
+ interface CompletionContext {
12
+ /** The current partial input being completed */
13
+ current?: string;
14
+ /** Previously parsed option values */
15
+ options?: Record<string, unknown>;
16
+ /** Previously parsed argument values */
17
+ args?: unknown[];
18
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Define a CLI option with full type inference from Zod schema.
3
+ * @type {import('./define-option.types.js').defineOption}
4
+ */
5
+ export function defineOption(optionDefinition) {
6
+ return optionDefinition;
7
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import { CompletionFunction } from './define-common.types.js';
3
+
4
+ /** Define a CLI option with full type inference from Zod schema. */
5
+ export function defineOption<S extends z.ZodType>(definition: OptionDefinition<S>): OptionDefinition<S>;
6
+
7
+ /** Option definition shape with Zod schema for type inference. */
8
+ export interface OptionDefinition<S extends z.ZodType = z.ZodType> {
9
+ /** The CLI option name (e.g., 'region' for --region). */
10
+ name: string;
11
+
12
+ /** Zod schema defining the option's type, default value, and validation. */
13
+ schema: S;
14
+
15
+ /** Human-readable description for help text. */
16
+ description: string;
17
+
18
+ /** Alternative names for this option (e.g., ['v'] for -v). */
19
+ aliases?: string[];
20
+
21
+ /** Placeholder text shown in help (e.g., 'ZONE' for --region <ZONE>). */
22
+ placeholder?: string;
23
+
24
+ /** Shell completion function. Can be sync or async. */
25
+ complete?: CompletionFunction;
26
+
27
+ /** Mark as deprecated. `true` for generic warning, or a string with migration instructions. */
28
+ deprecated?: boolean | string;
29
+ }
@@ -0,0 +1,86 @@
1
+ import { getDefault, isBoolean, isRequired } from './zod-utils.js';
2
+
3
+ /**
4
+ * @typedef {import('./get-command-info.types.d.ts').ArgumentInfo} ArgumentInfo
5
+ * @typedef {import('./get-command-info.types.d.ts').OptionInfo} OptionInfo
6
+ * @typedef {import('./get-command-info.types.d.ts').CommandInfo} CommandInfo
7
+ * @typedef {import('./define-command.types.d.ts').CommandDefinition} CommandDefinition
8
+ * @typedef {import('./define-option.types.d.ts').OptionDefinition} OptionDefinition
9
+ */
10
+
11
+ /**
12
+ * Extracts normalized command information for display purposes.
13
+ * This function provides a shared source of truth for CLI help, reference docs, and LLM docs.
14
+ * @param {string[]} path - Command path (e.g., ['env', 'set'])
15
+ * @param {CommandDefinition} definition
16
+ * @return {CommandInfo}
17
+ */
18
+ export function getCommandInfo(path, definition) {
19
+ const usageParts = ['clever', ...path];
20
+ if (definition.options != null) {
21
+ for (const option of Object.values(definition.options)) {
22
+ if (isRequired(option.schema)) {
23
+ usageParts.push(`--${option.name} <${option.placeholder ?? option.name}>`);
24
+ }
25
+ }
26
+ }
27
+ if (definition.args != null) {
28
+ for (const arg of definition.args) {
29
+ if (isRequired(arg.schema)) {
30
+ usageParts.push(`<${arg.placeholder}>`);
31
+ } else {
32
+ usageParts.push(`[<${arg.placeholder}>]`);
33
+ }
34
+ }
35
+ }
36
+ if (definition.options != null && Object.keys(definition.options).length > 0) {
37
+ usageParts.push('[options]');
38
+ }
39
+ const usage = usageParts.join(' ');
40
+
41
+ // Build args info (sorted by position, i.e., as defined)
42
+ const args = definition.args?.length
43
+ ? definition.args.map((arg) => {
44
+ return {
45
+ name: arg.placeholder,
46
+ description: arg.description,
47
+ optional: isRequired(arg.schema) ? null : '(optional)',
48
+ };
49
+ })
50
+ : null;
51
+
52
+ // Build options info (sorted: required first, then alphabetically)
53
+ const optionValues = Object.values(definition.options ?? {});
54
+ const options = optionValues.length
55
+ ? optionValues
56
+ .sort((optA, optB) => {
57
+ const aRequired = isRequired(optA.schema);
58
+ const bRequired = isRequired(optB.schema);
59
+ if (aRequired !== bRequired) return aRequired ? -1 : 1;
60
+ return optA.name.localeCompare(optB.name);
61
+ })
62
+ .map((option) => {
63
+ const shortAliases = (option.aliases?.filter((a) => a.length === 1) ?? []).map((a) => `-${a}`);
64
+ const longAliases = (option.aliases?.filter((a) => a.length > 1) ?? []).map((a) => `--${a}`);
65
+ const allAliases = [...shortAliases, `--${option.name}`, ...longAliases];
66
+ const defaultValue = getDefault(option.schema);
67
+
68
+ return {
69
+ name: option.name,
70
+ aliases: allAliases,
71
+ placeholder: isBoolean(option.schema) ? null : `<${option.placeholder ?? option.name}>`,
72
+ description: option.description,
73
+ deprecated:
74
+ typeof option.deprecated === 'string'
75
+ ? `(deprecated, ${option.deprecated})`
76
+ : option.deprecated === true
77
+ ? '(deprecated)'
78
+ : null,
79
+ required: isRequired(option.schema) ? '(required)' : null,
80
+ default: defaultValue ? `(default: ${defaultValue})` : null,
81
+ };
82
+ })
83
+ : null;
84
+
85
+ return { usage, args, options };
86
+ }
@@ -0,0 +1,42 @@
1
+ export interface ZodSchemaLike {
2
+ _def?: {
3
+ type?: string;
4
+ innerType?: ZodSchemaLike;
5
+ defaultValue?: unknown;
6
+ };
7
+ }
8
+
9
+ export interface ArgumentInfo {
10
+ /** The argument placeholder name */
11
+ name: string;
12
+ /** The argument description */
13
+ description: string;
14
+ /** '(optional)' or null */
15
+ optional: string | null;
16
+ }
17
+
18
+ export interface OptionInfo {
19
+ /** The option name (without dashes) */
20
+ name: string;
21
+ /** Aliases with dashes (short first, then name, then other long aliases) */
22
+ aliases: string[];
23
+ /** The option description */
24
+ description: string;
25
+ /** Placeholder, or null for booleans */
26
+ placeholder: string | null;
27
+ /** '(deprecated)', '(deprecated, with message)' or null */
28
+ deprecated: string | null;
29
+ /** '(required)' or null */
30
+ required: string | null;
31
+ /** '(default: value)' or null */
32
+ default: string | null;
33
+ }
34
+
35
+ export interface CommandInfo {
36
+ /** The usage line string */
37
+ usage: string;
38
+ /** Sorted by position, or null if no arguments */
39
+ args: ArgumentInfo[] | null;
40
+ /** Sorted by required first, then alphabetically, or null if no options */
41
+ options: OptionInfo[] | null;
42
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @typedef {Object} ZodSchemaLike
3
+ * @property {{ type?: string, innerType?: ZodSchemaLike, defaultValue?: unknown, typeName?: string, in?: ZodSchemaLike }} [_def]
4
+ */
5
+
6
+ /**
7
+ * Checks if a Zod schema is a boolean.
8
+ * Handles wrapped schemas (default, optional, nullable).
9
+ * @param {ZodSchemaLike} schema
10
+ * @return {boolean}
11
+ */
12
+ export function isBoolean(schema) {
13
+ const schemaType = schema._def?.type;
14
+ if (schemaType === 'boolean') return true;
15
+ if (schemaType === 'default' || schemaType === 'optional' || schemaType === 'nullable') {
16
+ const innerType = schema._def?.innerType;
17
+ if (innerType) return isBoolean(innerType);
18
+ }
19
+ return false;
20
+ }
21
+
22
+ /**
23
+ * Checks if a Zod schema is required (no default, not optional, not nullable).
24
+ * @param {ZodSchemaLike} schema
25
+ * @return {boolean}
26
+ */
27
+ export function isRequired(schema) {
28
+ const schemaType = schema._def?.type;
29
+ if (schemaType === 'default' || schemaType === 'optional' || schemaType === 'nullable') {
30
+ return false;
31
+ }
32
+ // For pipe schemas (created by .transform()), check the input schema
33
+ if (schemaType === 'pipe') {
34
+ const inputSchema = schema._def?.in;
35
+ if (inputSchema) return isRequired(inputSchema);
36
+ }
37
+ return true;
38
+ }
39
+
40
+ /**
41
+ * Extracts the default value from a Zod schema.
42
+ * Handles wrapped schemas (optional, nullable, pipe).
43
+ * @param {ZodSchemaLike} schema
44
+ * @return {unknown}
45
+ */
46
+ export function getDefault(schema) {
47
+ /** @type {ZodSchemaLike | undefined} */
48
+ let current = schema;
49
+ while (current) {
50
+ const schemaType = current._def?.type;
51
+ if (schemaType === 'default') {
52
+ return current._def?.defaultValue;
53
+ }
54
+ if (schemaType === 'optional' || schemaType === 'nullable') {
55
+ current = current._def?.innerType;
56
+ continue;
57
+ }
58
+ // For pipe schemas (created by .transform()), check the input schema
59
+ if (schemaType === 'pipe') {
60
+ current = current._def?.in;
61
+ continue;
62
+ }
63
+ break;
64
+ }
65
+ return undefined;
66
+ }
@@ -10,7 +10,6 @@ import { getAllLinkedAddons, linkAddon, unlinkAddon } from '@clevercloud/client/
10
10
  import { getAllAddonProviders } from '@clevercloud/client/esm/api/v2/product.js';
11
11
  import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
12
12
  import { getAddonProvider } from '@clevercloud/client/esm/api/v4/addon-providers.js';
13
- import cliparse from 'cliparse';
14
13
  import { confirm } from '../lib/prompts.js';
15
14
  import { Logger } from '../logger.js';
16
15
  import { resolveOwnerId } from './ids-resolver.js';
@@ -220,12 +219,12 @@ export async function rename(ownerId, addon, name) {
220
219
  }
221
220
 
222
221
  export function completeRegion() {
223
- return cliparse.autocomplete.words(['par', 'mtl']);
222
+ return ['par', 'mtl'];
224
223
  }
225
224
 
226
225
  // TODO: We need to fix this
227
226
  export function completePlan() {
228
- return cliparse.autocomplete.words(['dev', 's', 'm', 'l', 'xl', 'xxl']);
227
+ return ['dev', 's', 'm', 'l', 'xl', 'xxl'];
229
228
  }
230
229
 
231
230
  export async function findByName(addonName) {