clever-tools 4.4.0 → 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 (296) hide show
  1. package/bin/clever.js +208 -2128
  2. package/package.json +33 -25
  3. package/src/clever-client/auth-bridge.js +0 -9
  4. package/src/clever-client/drains.js +0 -17
  5. package/src/clever-client/operators.js +1 -1
  6. package/src/commands/README.md +65 -0
  7. package/src/commands/accesslogs/accesslogs.command.js +158 -0
  8. package/src/commands/accesslogs/accesslogs.docs.md +20 -0
  9. package/src/commands/{activity.js → activity/activity.command.js} +74 -44
  10. package/src/commands/activity/activity.docs.md +19 -0
  11. package/src/commands/addon/addon.args.js +14 -0
  12. package/src/commands/addon/addon.command.js +7 -0
  13. package/src/commands/addon/addon.create.command.js +236 -0
  14. package/src/commands/addon/addon.delete.command.js +32 -0
  15. package/src/commands/addon/addon.docs.md +156 -0
  16. package/src/commands/addon/addon.env.command.js +50 -0
  17. package/src/commands/addon/addon.list.command.js +55 -0
  18. package/src/commands/addon/addon.providers.command.js +45 -0
  19. package/src/commands/addon/addon.providers.show.command.js +99 -0
  20. package/src/commands/addon/addon.rename.command.js +24 -0
  21. package/src/commands/applications/applications.command.js +59 -0
  22. package/src/commands/applications/applications.docs.md +31 -0
  23. package/src/commands/applications/applications.list.command.js +100 -0
  24. package/src/commands/cancel-deploy/cancel-deploy.command.js +30 -0
  25. package/src/commands/cancel-deploy/cancel-deploy.docs.md +16 -0
  26. package/src/commands/config/config.args.js +10 -0
  27. package/src/commands/config/config.command.js +20 -0
  28. package/src/commands/config/config.docs.md +86 -0
  29. package/src/commands/config/config.get.command.js +21 -0
  30. package/src/commands/config/config.set.command.js +38 -0
  31. package/src/commands/config/config.update.command.js +88 -0
  32. package/src/commands/console/console.command.js +31 -0
  33. package/src/commands/console/console.docs.md +16 -0
  34. package/src/commands/create/create.command.js +173 -0
  35. package/src/commands/create/create.docs.md +27 -0
  36. package/src/commands/{curl.js → curl/curl.command.js} +10 -3
  37. package/src/commands/curl/curl.docs.md +9 -0
  38. package/src/commands/database/database.args.js +8 -0
  39. package/src/commands/database/database.backups.command.js +60 -0
  40. package/src/commands/database/database.backups.download.command.js +55 -0
  41. package/src/commands/database/database.command.js +10 -0
  42. package/src/commands/database/database.docs.md +52 -0
  43. package/src/commands/delete/delete.command.js +43 -0
  44. package/src/commands/delete/delete.docs.md +17 -0
  45. package/src/commands/deploy/deploy.command.js +166 -0
  46. package/src/commands/deploy/deploy.docs.md +22 -0
  47. package/src/commands/diag/diag.command.js +136 -0
  48. package/src/commands/diag/diag.docs.md +15 -0
  49. package/src/commands/domain/domain.add.command.js +25 -0
  50. package/src/commands/domain/domain.args.js +8 -0
  51. package/src/commands/domain/domain.command.js +38 -0
  52. package/src/commands/domain/domain.diag.command.js +204 -0
  53. package/src/commands/domain/domain.docs.md +143 -0
  54. package/src/commands/domain/domain.favourite.command.js +35 -0
  55. package/src/commands/domain/domain.favourite.set.command.js +24 -0
  56. package/src/commands/domain/domain.favourite.unset.command.js +23 -0
  57. package/src/commands/domain/domain.overview.command.js +157 -0
  58. package/src/commands/domain/domain.rm.command.js +25 -0
  59. package/src/commands/drain/drain.args.js +8 -0
  60. package/src/commands/drain/drain.command.js +56 -0
  61. package/src/commands/drain/drain.create.command.js +128 -0
  62. package/src/commands/drain/drain.disable.command.js +27 -0
  63. package/src/commands/drain/drain.docs.md +129 -0
  64. package/src/commands/drain/drain.enable.command.js +27 -0
  65. package/src/commands/drain/drain.get.command.js +38 -0
  66. package/src/commands/drain/drain.remove.command.js +26 -0
  67. package/src/commands/emails/emails.add.command.js +32 -0
  68. package/src/commands/emails/emails.args.js +8 -0
  69. package/src/commands/emails/emails.command.js +35 -0
  70. package/src/commands/emails/emails.docs.md +79 -0
  71. package/src/commands/emails/emails.open.command.js +15 -0
  72. package/src/commands/emails/emails.primary.command.js +29 -0
  73. package/src/commands/emails/emails.remove-all.command.js +54 -0
  74. package/src/commands/emails/emails.remove.command.js +25 -0
  75. package/src/commands/env/env.command.js +77 -0
  76. package/src/commands/env/env.docs.md +99 -0
  77. package/src/commands/env/env.import-vars.command.js +45 -0
  78. package/src/commands/env/env.import.command.js +29 -0
  79. package/src/commands/env/env.rm.command.js +25 -0
  80. package/src/commands/env/env.set.command.js +32 -0
  81. package/src/commands/features/features.args.js +9 -0
  82. package/src/commands/features/features.command.js +7 -0
  83. package/src/commands/features/features.disable.command.js +25 -0
  84. package/src/commands/features/features.docs.md +71 -0
  85. package/src/commands/features/features.enable.command.js +32 -0
  86. package/src/commands/features/features.info.command.js +27 -0
  87. package/src/commands/features/features.list.command.js +49 -0
  88. package/src/commands/global.args.js +45 -0
  89. package/src/commands/global.commands.js +461 -0
  90. package/src/commands/global.options.js +186 -0
  91. package/src/commands/help/help.command.js +9 -0
  92. package/src/commands/help/help.docs.md +9 -0
  93. package/src/commands/k8s/k8s.add-persistent-storage.command.js +39 -0
  94. package/src/commands/k8s/k8s.args.js +9 -0
  95. package/src/commands/k8s/k8s.command.js +12 -0
  96. package/src/commands/k8s/k8s.create.command.js +86 -0
  97. package/src/commands/k8s/k8s.delete.command.js +40 -0
  98. package/src/commands/k8s/k8s.docs.md +131 -0
  99. package/src/commands/k8s/k8s.get-kubeconfig.command.js +32 -0
  100. package/src/commands/k8s/k8s.get.command.js +43 -0
  101. package/src/commands/k8s/k8s.list.command.js +38 -0
  102. package/src/commands/keycloak/keycloak.command.js +17 -0
  103. package/src/commands/keycloak/keycloak.disable-ng.command.js +13 -0
  104. package/src/commands/keycloak/keycloak.docs.md +197 -0
  105. package/src/commands/keycloak/keycloak.enable-ng.command.js +13 -0
  106. package/src/commands/keycloak/keycloak.get.command.js +17 -0
  107. package/src/commands/keycloak/keycloak.open.command.js +13 -0
  108. package/src/commands/keycloak/keycloak.open.logs.command.js +13 -0
  109. package/src/commands/keycloak/keycloak.open.webui.command.js +13 -0
  110. package/src/commands/keycloak/keycloak.rebuild.command.js +13 -0
  111. package/src/commands/keycloak/keycloak.restart.command.js +13 -0
  112. package/src/commands/keycloak/keycloak.version.check.command.js +17 -0
  113. package/src/commands/keycloak/keycloak.version.command.js +17 -0
  114. package/src/commands/keycloak/keycloak.version.update.command.js +17 -0
  115. package/src/commands/kv/kv.command.js +99 -0
  116. package/src/commands/kv/kv.docs.md +27 -0
  117. package/src/commands/link/link.command.js +31 -0
  118. package/src/commands/link/link.docs.md +22 -0
  119. package/src/commands/{login.js → login/login.command.js} +44 -22
  120. package/src/commands/login/login.docs.md +16 -0
  121. package/src/commands/logout/logout.command.js +15 -0
  122. package/src/commands/logout/logout.docs.md +9 -0
  123. package/src/commands/logs/logs.command.js +81 -0
  124. package/src/commands/logs/logs.docs.md +22 -0
  125. package/src/commands/make-default/make-default.command.js +17 -0
  126. package/src/commands/make-default/make-default.docs.md +15 -0
  127. package/src/commands/matomo/matomo.command.js +17 -0
  128. package/src/commands/matomo/matomo.docs.md +109 -0
  129. package/src/commands/matomo/matomo.get.command.js +17 -0
  130. package/src/commands/matomo/matomo.open.command.js +13 -0
  131. package/src/commands/matomo/matomo.open.logs.command.js +13 -0
  132. package/src/commands/matomo/matomo.open.webui.command.js +13 -0
  133. package/src/commands/matomo/matomo.rebuild.command.js +13 -0
  134. package/src/commands/matomo/matomo.restart.command.js +13 -0
  135. package/src/commands/metabase/metabase.command.js +17 -0
  136. package/src/commands/metabase/metabase.docs.md +169 -0
  137. package/src/commands/metabase/metabase.get.command.js +17 -0
  138. package/src/commands/metabase/metabase.open.command.js +13 -0
  139. package/src/commands/metabase/metabase.open.logs.command.js +13 -0
  140. package/src/commands/metabase/metabase.open.webui.command.js +13 -0
  141. package/src/commands/metabase/metabase.rebuild.command.js +13 -0
  142. package/src/commands/metabase/metabase.restart.command.js +13 -0
  143. package/src/commands/metabase/metabase.version.check.command.js +17 -0
  144. package/src/commands/metabase/metabase.version.command.js +17 -0
  145. package/src/commands/metabase/metabase.version.update.command.js +17 -0
  146. package/src/commands/ng/ng.args.js +27 -0
  147. package/src/commands/ng/ng.command.js +45 -0
  148. package/src/commands/ng/ng.create.command.js +60 -0
  149. package/src/commands/ng/ng.create.external.command.js +44 -0
  150. package/src/commands/ng/ng.delete.command.js +22 -0
  151. package/src/commands/ng/ng.delete.external.command.js +25 -0
  152. package/src/commands/ng/ng.docs.md +214 -0
  153. package/src/commands/ng/ng.get-config.command.js +32 -0
  154. package/src/commands/ng/ng.get.command.js +22 -0
  155. package/src/commands/ng/ng.link.command.js +25 -0
  156. package/src/commands/ng/ng.options.js +9 -0
  157. package/src/commands/ng/ng.search.command.js +22 -0
  158. package/src/commands/ng/ng.unlink.command.js +25 -0
  159. package/src/commands/notify-email/notify-email.add.command.js +65 -0
  160. package/src/commands/notify-email/notify-email.command.js +61 -0
  161. package/src/commands/notify-email/notify-email.docs.md +60 -0
  162. package/src/commands/notify-email/notify-email.remove.command.js +24 -0
  163. package/src/commands/open/open.command.js +24 -0
  164. package/src/commands/open/open.docs.md +16 -0
  165. package/src/commands/otoroshi/otoroshi.command.js +17 -0
  166. package/src/commands/otoroshi/otoroshi.disable-ng.command.js +13 -0
  167. package/src/commands/otoroshi/otoroshi.docs.md +211 -0
  168. package/src/commands/otoroshi/otoroshi.enable-ng.command.js +13 -0
  169. package/src/commands/otoroshi/otoroshi.get-config.command.js +13 -0
  170. package/src/commands/otoroshi/otoroshi.get.command.js +17 -0
  171. package/src/commands/otoroshi/otoroshi.open.command.js +13 -0
  172. package/src/commands/otoroshi/otoroshi.open.logs.command.js +13 -0
  173. package/src/commands/otoroshi/otoroshi.open.webui.command.js +13 -0
  174. package/src/commands/otoroshi/otoroshi.rebuild.command.js +13 -0
  175. package/src/commands/otoroshi/otoroshi.restart.command.js +13 -0
  176. package/src/commands/otoroshi/otoroshi.version.check.command.js +17 -0
  177. package/src/commands/otoroshi/otoroshi.version.command.js +17 -0
  178. package/src/commands/otoroshi/otoroshi.version.update.command.js +17 -0
  179. package/src/commands/profile/profile.command.js +60 -0
  180. package/src/commands/profile/profile.docs.md +23 -0
  181. package/src/commands/profile/profile.open.command.js +12 -0
  182. package/src/commands/published-config/published-config.command.js +40 -0
  183. package/src/commands/published-config/published-config.docs.md +77 -0
  184. package/src/commands/published-config/published-config.import.command.js +29 -0
  185. package/src/commands/published-config/published-config.rm.command.js +27 -0
  186. package/src/commands/published-config/published-config.set.command.js +34 -0
  187. package/src/commands/restart/restart.command.js +77 -0
  188. package/src/commands/restart/restart.docs.md +21 -0
  189. package/src/commands/scale/scale.command.js +121 -0
  190. package/src/commands/scale/scale.docs.md +23 -0
  191. package/src/commands/service/service.command.js +91 -0
  192. package/src/commands/service/service.docs.md +104 -0
  193. package/src/commands/service/service.link-addon.command.js +24 -0
  194. package/src/commands/service/service.link-app.command.js +23 -0
  195. package/src/commands/service/service.unlink-addon.command.js +24 -0
  196. package/src/commands/service/service.unlink-app.command.js +23 -0
  197. package/src/commands/ssh/ssh.command.js +40 -0
  198. package/src/commands/ssh/ssh.docs.md +17 -0
  199. package/src/commands/ssh-keys/ssh-keys.add.command.js +41 -0
  200. package/src/commands/ssh-keys/ssh-keys.args.js +8 -0
  201. package/src/commands/ssh-keys/ssh-keys.command.js +50 -0
  202. package/src/commands/ssh-keys/ssh-keys.docs.md +66 -0
  203. package/src/commands/ssh-keys/ssh-keys.open.command.js +12 -0
  204. package/src/commands/ssh-keys/ssh-keys.remove-all.command.js +54 -0
  205. package/src/commands/ssh-keys/ssh-keys.remove.command.js +26 -0
  206. package/src/commands/status/status.command.js +122 -0
  207. package/src/commands/status/status.docs.md +17 -0
  208. package/src/commands/stop/stop.command.js +23 -0
  209. package/src/commands/stop/stop.docs.md +16 -0
  210. package/src/commands/tcp-redirs/tcp-redirs.add.command.js +24 -0
  211. package/src/commands/tcp-redirs/tcp-redirs.command.js +41 -0
  212. package/src/commands/tcp-redirs/tcp-redirs.docs.md +71 -0
  213. package/src/commands/tcp-redirs/tcp-redirs.list-namespaces.command.js +48 -0
  214. package/src/commands/tcp-redirs/tcp-redirs.options.js +11 -0
  215. package/src/commands/tcp-redirs/tcp-redirs.remove.command.js +34 -0
  216. package/src/commands/tokens/tokens.command.js +43 -0
  217. package/src/commands/tokens/tokens.create.command.js +108 -0
  218. package/src/commands/tokens/tokens.docs.md +50 -0
  219. package/src/commands/tokens/tokens.revoke.command.js +25 -0
  220. package/src/commands/unlink/unlink.command.js +21 -0
  221. package/src/commands/unlink/unlink.docs.md +15 -0
  222. package/src/commands/version/version.command.js +13 -0
  223. package/src/commands/version/version.docs.md +9 -0
  224. package/src/commands/webhooks/webhooks.add.command.js +51 -0
  225. package/src/commands/webhooks/webhooks.command.js +57 -0
  226. package/src/commands/webhooks/webhooks.docs.md +61 -0
  227. package/src/commands/webhooks/webhooks.remove.command.js +24 -0
  228. package/src/lib/cliparse-patched.js +192 -0
  229. package/src/lib/define-argument.js +7 -0
  230. package/src/lib/define-argument.types.d.ts +23 -0
  231. package/src/lib/define-command.js +7 -0
  232. package/src/lib/define-command.types.d.ts +85 -0
  233. package/src/lib/define-common.types.d.ts +18 -0
  234. package/src/lib/define-option.js +7 -0
  235. package/src/lib/define-option.types.d.ts +29 -0
  236. package/src/lib/get-command-info.js +86 -0
  237. package/src/lib/get-command-info.types.d.ts +42 -0
  238. package/src/lib/k8s.js +1 -1
  239. package/src/lib/zod-utils.js +66 -0
  240. package/src/models/addon.js +2 -19
  241. package/src/models/app_configuration.js +0 -30
  242. package/src/models/application.js +4 -5
  243. package/src/models/application_configuration.js +5 -23
  244. package/src/models/domain.js +34 -2
  245. package/src/models/exit-strategy-option.js +0 -9
  246. package/src/models/git.js +1 -4
  247. package/src/models/log-v4.js +15 -4
  248. package/src/models/log.js +5 -0
  249. package/src/models/namespaces.js +1 -2
  250. package/src/models/notification.js +1 -7
  251. package/src/parsers.js +33 -111
  252. package/src/command-options.js +0 -55
  253. package/src/command-promise-handler.js +0 -16
  254. package/src/commands/accesslogs.js +0 -138
  255. package/src/commands/addon.js +0 -391
  256. package/src/commands/applications.js +0 -123
  257. package/src/commands/cancel-deploy.js +0 -19
  258. package/src/commands/config.js +0 -47
  259. package/src/commands/console.js +0 -20
  260. package/src/commands/create.js +0 -129
  261. package/src/commands/database.js +0 -73
  262. package/src/commands/delete.js +0 -24
  263. package/src/commands/deploy.js +0 -133
  264. package/src/commands/diag.js +0 -126
  265. package/src/commands/domain.js +0 -445
  266. package/src/commands/drain.js +0 -164
  267. package/src/commands/emails.js +0 -156
  268. package/src/commands/env.js +0 -124
  269. package/src/commands/features.js +0 -87
  270. package/src/commands/k8s.js +0 -193
  271. package/src/commands/keycloak.js +0 -138
  272. package/src/commands/kv.js +0 -93
  273. package/src/commands/link.js +0 -20
  274. package/src/commands/logout.js +0 -8
  275. package/src/commands/logs.js +0 -45
  276. package/src/commands/makeDefault.js +0 -11
  277. package/src/commands/matomo.js +0 -85
  278. package/src/commands/metabase.js +0 -112
  279. package/src/commands/ng.js +0 -202
  280. package/src/commands/notify-email.js +0 -99
  281. package/src/commands/open.js +0 -13
  282. package/src/commands/otoroshi.js +0 -150
  283. package/src/commands/profile.js +0 -55
  284. package/src/commands/published-config.js +0 -70
  285. package/src/commands/restart.js +0 -52
  286. package/src/commands/scale.js +0 -66
  287. package/src/commands/service.js +0 -105
  288. package/src/commands/ssh-keys.js +0 -144
  289. package/src/commands/ssh.js +0 -20
  290. package/src/commands/status.js +0 -115
  291. package/src/commands/stop.js +0 -12
  292. package/src/commands/tcp-redirs.js +0 -80
  293. package/src/commands/tokens.js +0 -144
  294. package/src/commands/unlink.js +0 -14
  295. package/src/commands/version.js +0 -6
  296. package/src/commands/webhooks.js +0 -74
@@ -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,28 +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']);
229
- }
230
-
231
- export async function findById(addonId) {
232
- const { user, organisations } = await getSummary({}).then(sendToApi);
233
- for (const orga of [user, ...organisations]) {
234
- for (const simpleAddon of orga.addons) {
235
- if (simpleAddon.id === addonId) {
236
- const addon = await getAddon({ id: orga.id, addonId }).then(sendToApi);
237
- return {
238
- ...addon,
239
- orgaId: orga.id,
240
- };
241
- }
242
- }
243
- }
244
- throw new Error(`Could not find add-on with ID: ${addonId}`);
227
+ return ['dev', 's', 'm', 'l', 'xl', 'xxl'];
245
228
  }
246
229
 
247
230
  export async function findByName(addonName) {
@@ -131,27 +131,6 @@ function findDefaultApp(config) {
131
131
  );
132
132
  }
133
133
 
134
- async function getAppDetailsForId(appId) {
135
- const config = await loadApplicationConf();
136
-
137
- if (_.isEmpty(config.apps)) {
138
- throw new Error('There is no linked or targeted application. Use `--app` option or `clever link` command.');
139
- }
140
-
141
- const [appById, secondAppById] = _.filter(config.apps, { app_id: appId });
142
- if (appById == null) {
143
- throw new Error(`There are no applications matching id '${appId}'`);
144
- }
145
- if (secondAppById != null) {
146
- throw new Error(
147
- `There are several applications matching id '${appId}'.` +
148
- 'This should not happen, your `.clever.json` should be fixed.',
149
- );
150
- }
151
-
152
- return appById;
153
- }
154
-
155
134
  export async function getAppDetails({ alias }) {
156
135
  const config = await loadApplicationConf();
157
136
  const app = findApp(config, alias);
@@ -165,15 +144,6 @@ export async function getAppDetails({ alias }) {
165
144
  };
166
145
  }
167
146
 
168
- export async function getMostNaturalName(appId) {
169
- try {
170
- const details = await getAppDetailsForId(appId);
171
- return details.alias || details.name || appId;
172
- } catch {
173
- return appId;
174
- }
175
- }
176
-
177
147
  function persistConfig(modifiedConfig) {
178
148
  const jsonContents = JSON.stringify(modifiedConfig, null, 2);
179
149
  return fs.writeFile(conf.APP_CONFIGURATION_FILE, jsonContents);
@@ -11,7 +11,6 @@ import {
11
11
  } from '@clevercloud/client/esm/api/v2/application.js';
12
12
  import { getAvailableInstances } from '@clevercloud/client/esm/api/v2/product.js';
13
13
  import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
14
- import cliparse from 'cliparse';
15
14
  import _ from 'lodash';
16
15
  import { confirmAnswer } from '../lib/prompts.js';
17
16
  import { styleText } from '../lib/style-text.js';
@@ -23,7 +22,7 @@ import { sendToApi } from './send-to-api.js';
23
22
  import * as User from './user.js';
24
23
 
25
24
  export function listAvailableTypes() {
26
- return cliparse.autocomplete.words([
25
+ return [
27
26
  'docker',
28
27
  'elixir',
29
28
  'frankenphp',
@@ -46,17 +45,17 @@ export function listAvailableTypes() {
46
45
  'static-apache',
47
46
  'v',
48
47
  'war',
49
- ]);
48
+ ];
50
49
  }
51
50
 
52
51
  export const AVAILABLE_ZONES = ['par', 'parhds', 'grahds', 'rbx', 'rbxhds', 'scw', 'ldn', 'mtl', 'sgp', 'syd', 'wsw'];
53
52
 
54
53
  export function listAvailableZones() {
55
- return cliparse.autocomplete.words(AVAILABLE_ZONES);
54
+ return AVAILABLE_ZONES;
56
55
  }
57
56
 
58
57
  export function listAvailableAliases() {
59
- return AppConfiguration.loadApplicationConf().then(({ apps }) => cliparse.autocomplete.words(_.map(apps, 'alias')));
58
+ return AppConfiguration.loadApplicationConf().then(({ apps }) => _.map(apps, 'alias'));
60
59
  }
61
60
 
62
61
  export function listAvailableFlavors() {
@@ -1,4 +1,3 @@
1
- import cliparse from 'cliparse';
2
1
  import dedent from 'dedent';
3
2
  import { Logger } from '../logger.js';
4
3
 
@@ -80,29 +79,12 @@ export function parse(config, value) {
80
79
  }
81
80
  }
82
81
 
83
- export function getUpdateOptions() {
84
- return CONFIG_KEYS.map((config) => getConfigOptions(config)).reduce((a, b) => [...a, ...b], []);
85
- }
86
-
87
- function getConfigOptions(config) {
88
- switch (config.kind) {
89
- case 'bool':
90
- case 'inverted-bool':
91
- case 'force-https':
92
- case 'task': {
93
- return [
94
- cliparse.flag(`enable-${config.id}`, { description: `Enable ${config.id}` }),
95
- cliparse.flag(`disable-${config.id}`, { description: `Disable ${config.id}` }),
96
- ];
97
- }
98
- default: {
99
- return [cliparse.option(`${config.id}`, { description: `Set ${config.id}` })];
100
- }
101
- }
102
- }
103
-
104
82
  export function parseOptions(options) {
105
- const newOptions = CONFIG_KEYS.map((config) => parseConfigOption(config, options)).filter((a) => a != null);
83
+ const newOptions = CONFIG_KEYS.map((config) => {
84
+ return parseConfigOption(config, options);
85
+ }).filter((a) => {
86
+ return a != null && a[1] != null;
87
+ });
106
88
  return Object.fromEntries(newOptions);
107
89
  }
108
90
 
@@ -1,11 +1,15 @@
1
- import { getAllDomains, getFavouriteDomain } from '@clevercloud/client/esm/api/v2/application.js';
1
+ import {
2
+ getAllDomains,
3
+ getFavouriteDomain as getFavouriteDomainWithError,
4
+ } from '@clevercloud/client/esm/api/v2/application.js';
2
5
  import _ from 'lodash';
6
+ import { parse as parseDomain } from 'tldts';
3
7
  import { Logger } from '../logger.js';
4
8
  import { sendToApi } from './send-to-api.js';
5
9
 
6
10
  export async function getBest(appId, orgaId) {
7
11
  Logger.debug('Trying to get the favourite vhost for ' + appId);
8
- return getFavouriteDomain({ id: orgaId, appId })
12
+ return getFavouriteDomainWithError({ id: orgaId, appId })
9
13
  .then(sendToApi)
10
14
  .catch(async (e) => {
11
15
  if (e.response.status !== 404) {
@@ -35,3 +39,31 @@ export function selectBest(vhosts) {
35
39
  });
36
40
  return customVhost || withoutDefaultDomain || vhosts[0];
37
41
  }
42
+
43
+ export function getFavouriteDomain({ ownerId, appId }) {
44
+ return getFavouriteDomainWithError({ id: ownerId, appId })
45
+ .then(sendToApi)
46
+ .then(({ fqdn }) => fqdn)
47
+ .catch((error) => {
48
+ if (error.id === 4021) {
49
+ // No favourite vhost
50
+ return null;
51
+ }
52
+ throw error;
53
+ });
54
+ }
55
+
56
+ export function getDomainObject(domainWithPathPrefix, favouriteDomain) {
57
+ const parsed = parseDomain(domainWithPathPrefix, { validateHostname: false });
58
+ return {
59
+ domainWithPathPrefix,
60
+ domain: parsed.domain,
61
+ domainWithoutSuffix: parsed.domainWithoutSuffix,
62
+ hostname: parsed.hostname,
63
+ publicSuffix: parsed.publicSuffix,
64
+ subdomain: parsed.subdomain,
65
+ isApex: parsed.subdomain === '',
66
+ pathPrefix: new URL('https://' + domainWithPathPrefix).pathname,
67
+ isFavourite: domainWithPathPrefix === favouriteDomain,
68
+ };
69
+ }
@@ -1,17 +1,8 @@
1
- import { styleText } from '../lib/style-text.js';
2
- import { Logger } from '../logger.js';
3
-
4
1
  export function get(follow, exitOnDeploy) {
5
2
  if (follow) {
6
3
  if (exitOnDeploy === 'deploy-start') {
7
4
  throw new Error('The `follow` and `exit-on` set to "deploy-start" options are not compatible');
8
5
  }
9
- Logger.println(
10
- styleText(
11
- 'yellow',
12
- 'The `follow` option is deprecated and will be removed in an upcoming major, use --exit-on set to "never" instead',
13
- ),
14
- );
15
6
  return 'never';
16
7
  }
17
8
  return exitOnDeploy;
package/src/models/git.js CHANGED
@@ -1,4 +1,3 @@
1
- import cliparse from 'cliparse';
2
1
  import * as git from 'isomorphic-git';
3
2
  import _ from 'lodash';
4
3
  import fs from 'node:fs';
@@ -111,9 +110,7 @@ export async function push(remoteUrl, branchRefspec, force) {
111
110
  }
112
111
 
113
112
  export function completeBranches() {
114
- return getRepo()
115
- .then((repo) => git.listBranches(repo))
116
- .then(cliparse.autocomplete.words);
113
+ return getRepo().then((repo) => git.listBranches(repo));
117
114
  }
118
115
 
119
116
  export async function isShallow() {
@@ -133,12 +133,23 @@ export async function watchDeploymentAndDisplayLogs(options) {
133
133
  logsStream.close(quiet ? 'quiet' : 'follow');
134
134
  }
135
135
 
136
+ // deploymentEnded can be undefined if deferred resolved (e.g., stream closed via SIGINT)
137
+ if (deploymentEnded == null) {
138
+ return;
139
+ }
140
+
136
141
  if (deploymentEnded.state === 'OK') {
137
- const favouriteDomain = await getBest(appId, ownerId);
138
142
  Logger.println('');
139
- Logger.println(
140
- `${styleText(['bold', 'green'], '✓ Access your application:')} ${styleText(['underline', 'bold'], `https://${favouriteDomain.fqdn}`)}`,
141
- );
143
+
144
+ // There can be applications without any domain, so we don't fail if we can't get one
145
+ const favouriteDomain = await getBest(appId, ownerId).catch(() => null);
146
+
147
+ if (favouriteDomain) {
148
+ Logger.println(
149
+ `${styleText(['bold', 'green'], '✓ Access your application:')} ${styleText(['underline', 'bold'], `https://${favouriteDomain.fqdn}`)}`,
150
+ );
151
+ }
152
+
142
153
  Logger.println(
143
154
  `${styleText(['bold', 'blue'], '→ Manage your application:')} ${styleText(['underline', 'bold'], `${conf.GOTO_URL}/${appId}`)}`,
144
155
  );
package/src/models/log.js CHANGED
@@ -133,6 +133,11 @@ export async function watchDeploymentAndDisplayLogs({
133
133
  logsStream.close();
134
134
  }
135
135
 
136
+ // deploymentEnded can be undefined if deferred resolved (e.g., stream closed via SIGINT)
137
+ if (deploymentEnded == null) {
138
+ return;
139
+ }
140
+
136
141
  if (deploymentEnded.state === 'OK') {
137
142
  Logger.println(styleText(['bold', 'green'], 'Deployment successful'));
138
143
  } else if (deploymentEnded.state === 'CANCELLED') {
@@ -1,5 +1,4 @@
1
1
  import { getNamespaces as getTcpRedirNamespaces } from '@clevercloud/client/esm/api/v2/organisation.js';
2
- import cliparse from 'cliparse';
3
2
  import * as Application from './application.js';
4
3
  import { sendToApi } from './send-to-api.js';
5
4
 
@@ -11,5 +10,5 @@ export async function completeNamespaces() {
11
10
  // Sadly we do not have access to current params in complete as of now
12
11
  const { ownerId } = await Application.resolveId(null, null);
13
12
 
14
- return getNamespaces(ownerId).then(cliparse.autocomplete.words);
13
+ return getNamespaces(ownerId);
15
14
  }
@@ -1,15 +1,9 @@
1
- import cliparse from 'cliparse';
2
1
  import * as AppConfig from './app_configuration.js';
3
2
  import * as Organisation from './organisation.js';
4
3
  import * as User from './user.js';
5
4
 
6
5
  export function listMetaEvents() {
7
- return cliparse.autocomplete.words([
8
- 'META_SERVICE_LIFECYCLE',
9
- 'META_DEPLOYMENT_RESULT',
10
- 'META_SERVICE_MANAGEMENT',
11
- 'META_CREDITS',
12
- ]);
6
+ return ['META_SERVICE_LIFECYCLE', 'META_DEPLOYMENT_RESULT', 'META_SERVICE_MANAGEMENT', 'META_CREDITS'];
13
7
  }
14
8
 
15
9
  export function getOrgaIdOrUserId(orgIdOrName) {
package/src/parsers.js CHANGED
@@ -1,4 +1,3 @@
1
- import cliparse from 'cliparse';
2
1
  import ISO8601 from 'iso8601-duration';
3
2
  import * as Application from './models/application.js';
4
3
  import { NG_MEMBER_PREFIXES } from './models/ng.js';
@@ -9,92 +8,63 @@ export function addonOptions(options) {
9
8
  const optionsArray = typeof options === 'string' ? [options] : options;
10
9
  for (const option of optionsArray) {
11
10
  if (!option.match(addonOptionsRegex)) {
12
- return cliparse.parsers.error('Invalid option: ' + option);
11
+ throw new Error('Invalid option: ' + option);
13
12
  }
14
13
  }
15
- return cliparse.parsers.success(optionsArray.join(','));
14
+ return optionsArray.join(',');
16
15
  }
17
16
 
18
17
  export function flavor(flavor) {
19
18
  const flavors = Application.listAvailableFlavors();
20
19
  if (flavors.includes(flavor)) {
21
- return cliparse.parsers.success(flavor);
20
+ return flavor;
22
21
  }
23
- return cliparse.parsers.error('Invalid value: ' + flavor);
22
+ throw new Error('Invalid value: ' + flavor);
24
23
  }
25
24
 
26
25
  export function buildFlavor(flavorOrDisabled) {
27
26
  if (flavorOrDisabled === 'disabled') {
28
- return cliparse.parsers.success(flavorOrDisabled);
27
+ return flavorOrDisabled;
29
28
  }
30
29
  return flavor(flavorOrDisabled);
31
30
  }
32
31
 
33
- export function instances(instances) {
34
- const parsedInstances = parseInt(instances, 10);
35
- if (isNaN(parsedInstances)) {
36
- return cliparse.parsers.error('Invalid number: ' + instances);
37
- }
38
- if (parsedInstances < 1 || parsedInstances > 20) {
39
- return cliparse.parsers.error('The number of instances must be between 1 and 20');
40
- }
41
- return cliparse.parsers.success(parsedInstances);
42
- }
43
-
44
32
  export function date(dateString) {
45
33
  const date = new Date(dateString);
46
34
  if (isNaN(dateString) && !isNaN(date.getTime())) {
47
- return cliparse.parsers.success(date);
35
+ return date;
48
36
  }
49
37
 
50
- const duration = durationInSeconds(dateString);
51
- if (duration.success) {
52
- return cliparse.parsers.success(new Date(Date.now() - duration.success * 1000));
53
- }
54
-
55
- return duration;
38
+ const seconds = durationInSeconds(dateString);
39
+ return new Date(Date.now() - seconds * 1000);
56
40
  }
57
41
 
58
42
  export function futureDateOrDuration(dateString) {
59
43
  const date = new Date(dateString);
60
44
  if (isNaN(dateString) && !isNaN(date.getTime())) {
61
- return cliparse.parsers.success(date);
62
- }
63
-
64
- const duration = durationInSeconds(dateString);
65
- if (duration.success) {
66
- return cliparse.parsers.success(new Date(Date.now() + duration.success * 1000));
45
+ return date;
67
46
  }
68
47
 
69
- return duration;
70
- }
71
-
72
- // This simple regex is enough for our use cases
73
- const emailRegex = /^\S+@\S+\.\S+$/g;
74
-
75
- export function email(string) {
76
- if (string.match(emailRegex)) {
77
- return cliparse.parsers.success(string);
78
- }
79
- return cliparse.parsers.error('Invalid email');
48
+ const seconds = durationInSeconds(dateString);
49
+ return new Date(Date.now() + seconds * 1000);
80
50
  }
81
51
 
82
52
  const appIdRegex = /^app_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
83
53
 
84
54
  export function appIdOrName(string) {
85
55
  if (string.match(appIdRegex)) {
86
- return cliparse.parsers.success({ app_id: string });
56
+ return { app_id: string };
87
57
  }
88
- return cliparse.parsers.success({ app_name: string });
58
+ return { app_name: string };
89
59
  }
90
60
 
91
61
  const orgaIdRegex = /^(user_|orga_)[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
92
62
 
93
63
  export function orgaIdOrName(string) {
94
64
  if (string.match(orgaIdRegex)) {
95
- return cliparse.parsers.success({ orga_id: string });
65
+ return { orga_id: string };
96
66
  }
97
- return cliparse.parsers.success({ orga_name: string });
67
+ return { orga_name: string };
98
68
  }
99
69
 
100
70
  const addonIdRegex = /^addon_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
@@ -104,31 +74,16 @@ const ulidRegex = /^(kubernetes)_[0-9A-HJ-NP-TV-Z]{26}$/i;
104
74
 
105
75
  export function addonIdOrName(string) {
106
76
  if (string.match(addonIdRegex)) {
107
- return cliparse.parsers.success({ addon_id: string });
77
+ return { addon_id: string };
108
78
  }
109
79
  if (string.match(operatorIdRegex) || string.match(ulidRegex)) {
110
- return cliparse.parsers.success({ operator_id: string });
80
+ return { operator_id: string };
111
81
  }
112
- return cliparse.parsers.success({ addon_name: string });
82
+ return { addon_name: string };
113
83
  }
114
84
 
115
85
  export function commaSeparated(string) {
116
- return cliparse.parsers.success(string.split(','));
117
- }
118
-
119
- export function integer(string) {
120
- const integer = parseInt(string);
121
- if (isNaN(integer)) {
122
- return cliparse.parsers.error('Invalid number: ' + string);
123
- }
124
- return cliparse.parsers.success(integer);
125
- }
126
-
127
- export function nonEmptyString(string) {
128
- if (typeof string !== 'string' || string === '') {
129
- return cliparse.parsers.error('Invalid string, it should not be empty');
130
- }
131
- return cliparse.parsers.success(string);
86
+ return string.split(',');
132
87
  }
133
88
 
134
89
  // /^[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?$/i;
@@ -136,41 +91,20 @@ const tagRegex = /^[^,\s]+$/;
136
91
 
137
92
  export function tag(string) {
138
93
  if (string.match(tagRegex)) {
139
- return cliparse.parsers.success(string);
94
+ return string;
140
95
  }
141
- return cliparse.parsers.error(`Invalid tag '${string}'. Should match ${tagRegex}`);
96
+ throw new Error(`Invalid tag '${string}'. Should match ${tagRegex}`);
142
97
  }
143
98
 
144
99
  export function tags(string) {
145
100
  if (String(string).length === 0) {
146
- return cliparse.parsers.success([]);
101
+ return [];
147
102
  }
148
103
  const tags = String(string).split(',');
149
104
  for (const current of tags) {
150
- if (tag(current).error) {
151
- return cliparse.parsers.error(`Invalid tag '${current}'. Should match \`${tagRegex}\``);
152
- }
153
- }
154
- return cliparse.parsers.success(tags);
155
- }
156
-
157
- export const ipAddressRegex =
158
- /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])$/;
159
-
160
- export function ipAddress(string) {
161
- if (string.match(ipAddressRegex)) {
162
- return cliparse.parsers.success(string);
105
+ tag(current); // will throw if invalid
163
106
  }
164
- return cliparse.parsers.error(`Invalid IP address '${string}'. Should match ${ipAddressRegex}`);
165
- }
166
-
167
- export const portNumberRegex = /^\d{1,5}$/;
168
-
169
- export function portNumber(number) {
170
- if (String(number).match(portNumberRegex)) {
171
- return cliparse.parsers.success(number);
172
- }
173
- return cliparse.parsers.error(`Invalid port number '${number}'. Should match ${portNumberRegex}`);
107
+ return tags;
174
108
  }
175
109
 
176
110
  /**
@@ -180,29 +114,25 @@ export function portNumber(number) {
180
114
  * @returns {number} number of seconds
181
115
  */
182
116
  export function durationInSeconds(durationStr = '') {
183
- const failed = cliparse.parsers.error(
184
- `Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`,
185
- );
117
+ const errorMessage = `Invalid duration: "${durationStr}", expect (IS0 8601 duration / a "1h, 1m, 30s" like duration / a positive number in seconds)`;
186
118
 
187
119
  if (durationStr.startsWith('P')) {
188
120
  try {
189
121
  const d = ISO8601.parse(durationStr);
190
- return cliparse.parsers.success(ISO8601.toSeconds(d));
122
+ return ISO8601.toSeconds(d);
191
123
  } catch {
192
- return failed;
124
+ throw new Error(errorMessage);
193
125
  }
194
126
  }
195
127
 
196
128
  try {
197
- const durationInSeconds = parseSimpleDuration(durationStr);
198
- return cliparse.parsers.success(durationInSeconds);
129
+ return parseSimpleDuration(durationStr);
199
130
  } catch {
200
131
  const n = Number.parseInt(durationStr);
201
132
  if (isNaN(n) || n < 0) {
202
- return failed;
133
+ throw new Error(errorMessage);
203
134
  }
204
-
205
- return cliparse.parsers.success(n);
135
+ return n;
206
136
  }
207
137
  }
208
138
 
@@ -230,18 +160,10 @@ function parseSimpleDuration(durationStr) {
230
160
  // Network Groups parsers
231
161
  export function ngResourceType(string) {
232
162
  if (string.startsWith('ng_')) {
233
- return cliparse.parsers.success({ ngId: string });
163
+ return { ngId: string };
234
164
  }
235
165
  if (Object.keys(NG_MEMBER_PREFIXES).some((prefix) => string.startsWith(prefix))) {
236
- return cliparse.parsers.success({ memberId: string });
237
- }
238
- return cliparse.parsers.success({ ngResourceLabel: string });
239
- }
240
-
241
- export function ngValidType(string) {
242
- if (string === 'NetworkGroup' || string === 'Member' || string === 'CleverPeer' || string === 'ExternalPeer') {
243
- return cliparse.parsers.success(string);
244
- } else {
245
- return cliparse.parsers.error(`Invalid Network Group resource type: ${string}`);
166
+ return { memberId: string };
246
167
  }
168
+ return { ngResourceLabel: string };
247
169
  }
@@ -1,55 +0,0 @@
1
- import cliparse from 'cliparse';
2
-
3
- export function getOutputFormatOption(formats = []) {
4
- const availableFormats = ['human', 'json', ...formats];
5
- return cliparse.option('format', {
6
- aliases: ['F'],
7
- metavar: 'format',
8
- parser: (format) => {
9
- return availableFormats.includes(format)
10
- ? cliparse.parsers.success(format)
11
- : cliparse.parsers.error('The output format must be one of ' + availableFormats.join(', '));
12
- },
13
- default: 'human',
14
- description: `Output format (${availableFormats.join(', ')})`,
15
- complete() {
16
- return cliparse.autocomplete.words(availableFormats);
17
- },
18
- });
19
- }
20
-
21
- export function getSameCommitPolicyOption() {
22
- const availablePolicies = ['error', 'ignore', 'restart', 'rebuild'];
23
- return cliparse.option('same-commit-policy', {
24
- aliases: ['p'],
25
- metavar: 'policy',
26
- parser: (policy) => {
27
- return availablePolicies.includes(policy)
28
- ? cliparse.parsers.success(policy)
29
- : cliparse.parsers.error(`the policy must be one of ${availablePolicies.join(', ')}`);
30
- },
31
- default: 'error',
32
- description: `What to do when local and remote commit are identical (${availablePolicies.join(', ')})`,
33
- complete() {
34
- return cliparse.autocomplete.words(availablePolicies);
35
- },
36
- });
37
- }
38
-
39
- export function getExitOnOption() {
40
- const availableExitOn = ['deploy-start', 'deploy-end', 'never'];
41
- return cliparse.option('exit-on', {
42
- aliases: ['e'],
43
- metavar: 'step',
44
- parser: (exitOnStrategy) => {
45
- return availableExitOn.includes(exitOnStrategy)
46
- ? cliparse.parsers.success(exitOnStrategy)
47
- : cliparse.parsers.error(`The exit-on strategy must be one of ${availableExitOn.join(', ')}`);
48
- },
49
- default: 'deploy-end',
50
- description: `Step at which the logs streaming is ended, steps are: ${availableExitOn.join(', ')}`,
51
- complete() {
52
- return cliparse.autocomplete.words(availableExitOn);
53
- },
54
- });
55
- }
@@ -1,16 +0,0 @@
1
- import semver from 'semver';
2
- import pkg from '../package.json' with { type: 'json' };
3
- import { Logger } from './logger.js';
4
-
5
- export function handleCommandPromise(promise) {
6
- promise.catch((error) => {
7
- Logger.error(error);
8
- const semverIsOk = semver.satisfies(process.version, pkg.engines.node);
9
- if (!semverIsOk) {
10
- Logger.warn(
11
- `You are using node ${process.version}, some of our commands require node ${pkg.engines.node}. The error may be caused by this.`,
12
- );
13
- }
14
- process.exit(1);
15
- });
16
- }