clever-tools 3.14.0 → 4.0.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 (93) hide show
  1. package/README.md +130 -37
  2. package/bin/clever.js +1427 -718
  3. package/package.json +61 -77
  4. package/src/clever-client/auth-bridge.js +9 -12
  5. package/src/clever-client/ng.js +1 -1
  6. package/src/clever-client/operators.js +7 -7
  7. package/src/command-options.js +6 -6
  8. package/src/command-promise-handler.js +6 -6
  9. package/src/commands/accesslogs.js +38 -29
  10. package/src/commands/activity.js +62 -40
  11. package/src/commands/addon.js +65 -69
  12. package/src/commands/applications.js +33 -31
  13. package/src/commands/cancel-deploy.js +7 -7
  14. package/src/commands/config.js +9 -7
  15. package/src/commands/console.js +3 -3
  16. package/src/commands/create.js +32 -31
  17. package/src/commands/curl.js +14 -36
  18. package/src/commands/database.js +10 -30
  19. package/src/commands/delete.js +8 -8
  20. package/src/commands/deploy.js +60 -46
  21. package/src/commands/diag.js +27 -25
  22. package/src/commands/domain.js +89 -91
  23. package/src/commands/drain.js +26 -14
  24. package/src/commands/emails.js +24 -28
  25. package/src/commands/env.js +18 -18
  26. package/src/commands/features.js +12 -18
  27. package/src/commands/keycloak.js +11 -11
  28. package/src/commands/kv.js +13 -13
  29. package/src/commands/link.js +9 -8
  30. package/src/commands/login.js +19 -27
  31. package/src/commands/logout.js +1 -1
  32. package/src/commands/logs.js +20 -12
  33. package/src/commands/makeDefault.js +5 -5
  34. package/src/commands/matomo.js +7 -7
  35. package/src/commands/metabase.js +9 -9
  36. package/src/commands/ng.js +32 -32
  37. package/src/commands/notify-email.js +11 -15
  38. package/src/commands/open.js +1 -1
  39. package/src/commands/otoroshi.js +11 -11
  40. package/src/commands/profile.js +8 -8
  41. package/src/commands/published-config.js +11 -11
  42. package/src/commands/restart.js +15 -8
  43. package/src/commands/scale.js +25 -16
  44. package/src/commands/service.js +18 -9
  45. package/src/commands/ssh-keys.js +25 -29
  46. package/src/commands/ssh.js +1 -2
  47. package/src/commands/status.js +31 -22
  48. package/src/commands/stop.js +3 -3
  49. package/src/commands/tcp-redirs.js +27 -26
  50. package/src/commands/tokens.js +44 -43
  51. package/src/commands/unlink.js +7 -5
  52. package/src/commands/version.js +2 -4
  53. package/src/commands/webhooks.js +8 -10
  54. package/src/experimental-features.js +7 -5
  55. package/src/format-table.js +46 -15
  56. package/src/initial-setup.js +2 -32
  57. package/src/initial-update-notifier.js +18 -0
  58. package/src/lib/has-param.js +16 -0
  59. package/src/lib/ng-print.js +21 -24
  60. package/src/lib/operator-commands.js +58 -53
  61. package/src/lib/prompts.js +5 -5
  62. package/src/lib/slugify.js +1 -1
  63. package/src/logger.js +24 -22
  64. package/src/models/activity.js +3 -3
  65. package/src/models/addon.js +52 -53
  66. package/src/models/app_configuration.js +34 -32
  67. package/src/models/application.js +90 -77
  68. package/src/models/application_configuration.js +19 -27
  69. package/src/models/configuration.js +30 -32
  70. package/src/models/deployments.js +9 -19
  71. package/src/models/domain.js +10 -9
  72. package/src/models/drain.js +16 -15
  73. package/src/models/exit-strategy-option.js +15 -5
  74. package/src/models/fs-utils.js +4 -3
  75. package/src/models/git.js +26 -32
  76. package/src/models/ids-resolver.js +37 -41
  77. package/src/models/isomorphic-http-with-agent.js +3 -3
  78. package/src/models/json-array.js +5 -6
  79. package/src/models/log-v4.js +44 -52
  80. package/src/models/log.js +40 -45
  81. package/src/models/namespaces.js +4 -4
  82. package/src/models/ng-resources.js +49 -39
  83. package/src/models/ng.js +41 -40
  84. package/src/models/node-dns-resolver.js +3 -3
  85. package/src/models/notification.js +7 -10
  86. package/src/models/operator.js +8 -10
  87. package/src/models/organisation.js +5 -8
  88. package/src/models/send-to-api.js +18 -11
  89. package/src/models/user.js +6 -5
  90. package/src/models/utils.js +5 -8
  91. package/src/models/variables.js +18 -20
  92. package/src/parsers.js +34 -34
  93. package/src/load-package-json.cjs +0 -5
@@ -1,20 +1,16 @@
1
- import { promisify } from 'node:util';
1
+ import { getAllDeployments, getDeployment } from '@clevercloud/client/esm/api/v2/application.js';
2
+ import { setTimeout as delay } from 'node:timers/promises';
2
3
  import { Logger } from '../logger.js';
3
- import { getDeployment, getAllDeployments } from '@clevercloud/client/esm/api/v2/application.js';
4
4
  import { sendToApi } from './send-to-api.js';
5
5
 
6
- const delay = promisify(setTimeout);
7
-
8
6
  const DEPLOYMENT_POLLING_DELAY = 5000;
9
7
  const BACKOFF_FACTOR = 1.25;
10
8
  const INIT_RETRY_TIMEOUT = 1500;
11
9
  const MAX_RETRY_COUNT = 5;
12
10
 
13
- export async function waitForDeploymentStart ({ ownerId, appId, deploymentId, commitId, knownDeployments }) {
14
-
11
+ export async function waitForDeploymentStart({ ownerId, appId, deploymentId, commitId, knownDeployments }) {
15
12
  return waitFor(async () => {
16
13
  try {
17
-
18
14
  // In a deploy situation, we don't have the deployment ID so we get the latest deployments,
19
15
  // then we match by commit ID and we filter out "known deployments" that existed before the deploy.
20
16
  // In a restart situation, we have a deployment ID but fetching it too soon may result in an error so we get latest deployments,
@@ -35,15 +31,14 @@ export async function waitForDeploymentStart ({ ownerId, appId, deploymentId, co
35
31
  return deployment;
36
32
  }
37
33
  Logger.debug('Deployment cannot be found yet');
38
- }
39
- catch (e) {
34
+ } catch (e) {
40
35
  Logger.debug('Failed to retrieve deployment');
41
36
  throw e;
42
37
  }
43
38
  });
44
39
  }
45
40
 
46
- export async function waitForDeploymentEnd ({ ownerId, appId, deploymentId }) {
41
+ export async function waitForDeploymentEnd({ ownerId, appId, deploymentId }) {
47
42
  return waitFor(async () => {
48
43
  try {
49
44
  const deployment = await getDeployment({ id: ownerId, appId, deploymentId }).then(sendToApi);
@@ -53,8 +48,7 @@ export async function waitForDeploymentEnd ({ ownerId, appId, deploymentId }) {
53
48
  return deployment;
54
49
  }
55
50
  Logger.debug(`Deployment is not finished yet (state:${deployment.state})`);
56
- }
57
- catch (e) {
51
+ } catch (e) {
58
52
  Logger.debug('Failed to retrieve current deployment status');
59
53
  throw e;
60
54
  }
@@ -65,14 +59,11 @@ export async function waitForDeploymentEnd ({ ownerId, appId, deploymentId }) {
65
59
  // Return fetchResult's result if it's not null
66
60
  // Retry with simple "infinite polling" if fetchResult succeeds and returns null
67
61
  // Retry with exponential backoff if fetchResult fails
68
- async function waitFor (fetchResult) {
69
-
62
+ async function waitFor(fetchResult) {
70
63
  let failCount = 0;
71
64
 
72
65
  while (true) {
73
-
74
66
  try {
75
-
76
67
  const result = await fetchResult();
77
68
  if (result != null) {
78
69
  return result;
@@ -83,8 +74,7 @@ async function waitFor (fetchResult) {
83
74
 
84
75
  // Retry with simple polling when API calls succeed
85
76
  await delay(DEPLOYMENT_POLLING_DELAY);
86
- }
87
- catch (e) {
77
+ } catch (e) {
88
78
  // If only retry if it's a network error
89
79
  if (e.code !== 'EAI_AGAIN') {
90
80
  throw e;
@@ -97,7 +87,7 @@ async function waitFor (fetchResult) {
97
87
  }
98
88
 
99
89
  // If API call fails, retry with an exponential backoff
100
- await delay(INIT_RETRY_TIMEOUT * (BACKOFF_FACTOR ** failCount));
90
+ await delay(INIT_RETRY_TIMEOUT * BACKOFF_FACTOR ** failCount);
101
91
  }
102
92
  }
103
93
  }
@@ -1,14 +1,13 @@
1
+ import { getAllDomains, getFavouriteDomain } from '@clevercloud/client/esm/api/v2/application.js';
1
2
  import _ from 'lodash';
2
-
3
3
  import { Logger } from '../logger.js';
4
- import { getAllDomains, getFavouriteDomain } from '@clevercloud/client/esm/api/v2/application.js';
5
- import { sendToApi } from '../models/send-to-api.js';
4
+ import { sendToApi } from './send-to-api.js';
6
5
 
7
- export async function getBest (appId, orgaId) {
6
+ export async function getBest(appId, orgaId) {
8
7
  Logger.debug('Trying to get the favourite vhost for ' + appId);
9
- return getFavouriteDomain({ id: orgaId, appId }).then(sendToApi)
8
+ return getFavouriteDomain({ id: orgaId, appId })
9
+ .then(sendToApi)
10
10
  .catch(async (e) => {
11
-
12
11
  if (e.response.status !== 404) {
13
12
  throw e;
14
13
  }
@@ -18,19 +17,21 @@ export async function getBest (appId, orgaId) {
18
17
  const result = selectBest(allDomains);
19
18
 
20
19
  if (result == null) {
21
- throw new Error('Couldn\'t find a domain name');
20
+ throw new Error("Couldn't find a domain name");
22
21
  }
23
22
 
24
23
  return result;
25
24
  });
26
25
  }
27
26
 
28
- export function selectBest (vhosts) {
27
+ export function selectBest(vhosts) {
29
28
  const customVhost = _.find(vhosts, (vhost) => {
30
29
  return !vhost.fqdn.endsWith('.cleverapps.io');
31
30
  });
32
31
  const withoutDefaultDomain = _.find(vhosts, (vhost) => {
33
- return !vhost.fqdn.match(/^app-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.cleverapps\.io$/);
32
+ return !vhost.fqdn.match(
33
+ /^app-[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.cleverapps\.io$/,
34
+ );
34
35
  });
35
36
  return customVhost || withoutDefaultDomain || vhosts[0];
36
37
  }
@@ -9,10 +9,11 @@ const DRAIN_TYPES = [
9
9
  { id: 'NewRelicHTTP', apiKey: 'MANDATORY' },
10
10
  ];
11
11
 
12
- export function createDrainBody (appId, drainTargetURL, drainTargetType, drainTargetCredentials, drainTargetConfig) {
13
-
12
+ export function createDrainBody(appId, drainTargetURL, drainTargetType, drainTargetCredentials, drainTargetConfig) {
14
13
  if (!authorizeDrainCreation(drainTargetType, drainTargetCredentials, drainTargetConfig)) {
15
- throw new Error("Credentials are: optional for HTTP, mandatory for ElasticSearch, NewRelicHTTP and TCPSyslog/UDPSyslog don't need them.");
14
+ throw new Error(
15
+ "Credentials are: optional for HTTP, mandatory for ElasticSearch, NewRelicHTTP and TCPSyslog/UDPSyslog don't need them.",
16
+ );
16
17
  }
17
18
 
18
19
  const body = {
@@ -37,7 +38,7 @@ export function createDrainBody (appId, drainTargetURL, drainTargetType, drainTa
37
38
  return body;
38
39
  }
39
40
 
40
- export function authorizeDrainCreation (drainTargetType, drainTargetCredentials, drainTargetConfig) {
41
+ export function authorizeDrainCreation(drainTargetType, drainTargetCredentials, drainTargetConfig) {
41
42
  if (drainTypeExists(drainTargetType)) {
42
43
  // retrieve field for drain type ('mandatory', 'optional', undefined)
43
44
  const credStatus = fieldStatus(drainTargetType).credentials;
@@ -87,46 +88,46 @@ export function authorizeDrainCreation (drainTargetType, drainTargetCredentials,
87
88
  }
88
89
  }
89
90
 
90
- function fieldStatus (drainTargetType) {
91
+ function fieldStatus(drainTargetType) {
91
92
  return DRAIN_TYPES.find(({ id }) => id === drainTargetType);
92
93
  }
93
94
 
94
- function drainTypeExists (drainTargetType) {
95
+ function drainTypeExists(drainTargetType) {
95
96
  return DRAIN_TYPES.some(({ id }) => id === drainTargetType);
96
97
  }
97
98
 
98
- function credentialsExist ({ username, password }) {
99
+ function credentialsExist({ username, password }) {
99
100
  return username != null && password != null;
100
101
  }
101
102
 
102
- function credentialsEmpty ({ username, password }) {
103
+ function credentialsEmpty({ username, password }) {
103
104
  return username == null && password == null;
104
105
  }
105
106
 
106
- function indexPrefixExist ({ indexPrefix }) {
107
+ function indexPrefixExist({ indexPrefix }) {
107
108
  return indexPrefix != null;
108
109
  }
109
110
 
110
- function indexPrefixEmpty ({ indexPrefix }) {
111
+ function indexPrefixEmpty({ indexPrefix }) {
111
112
  return indexPrefix == null;
112
113
  }
113
114
 
114
- function structuredDataParametersExist ({ structuredDataParameters }) {
115
+ function structuredDataParametersExist({ structuredDataParameters }) {
115
116
  return structuredDataParameters != null;
116
117
  }
117
118
 
118
- function structuredDataParametersEmpty ({ structuredDataParameters }) {
119
+ function structuredDataParametersEmpty({ structuredDataParameters }) {
119
120
  return structuredDataParameters == null;
120
121
  }
121
122
 
122
- function keyExist ({ apiKey }) {
123
+ function keyExist({ apiKey }) {
123
124
  return apiKey != null;
124
125
  }
125
126
 
126
- function keyEmpty ({ apiKey }) {
127
+ function keyEmpty({ apiKey }) {
127
128
  return apiKey == null;
128
129
  }
129
130
 
130
- export function listDrainTypes () {
131
+ export function listDrainTypes() {
131
132
  return cliparse.autocomplete.words(DRAIN_TYPES.map((type) => type.id));
132
133
  }
@@ -1,20 +1,30 @@
1
- import colors from 'colors/safe.js';
1
+ import { styleText } from 'node:util';
2
2
  import { Logger } from '../logger.js';
3
3
 
4
- export function get (follow, exitOnDeploy) {
4
+ export function get(follow, exitOnDeploy) {
5
5
  if (follow) {
6
6
  if (exitOnDeploy === 'deploy-start') {
7
7
  throw new Error('The `follow` and `exit-on` set to "deploy-start" options are not compatible');
8
8
  }
9
- Logger.println(colors.yellow('The `follow` option is deprecated and will be removed in an upcoming major, use --exit-on set to "never" instead'));
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
+ );
10
15
  return 'never';
11
16
  }
12
17
  return exitOnDeploy;
13
18
  }
14
19
 
15
20
  // plotQuietWarning: If in quiet mode and exitStrategy set to never plot a warning to indicate that the command will end
16
- export function plotQuietWarning (exitStrategy, quiet) {
21
+ export function plotQuietWarning(exitStrategy, quiet) {
17
22
  if (exitStrategy === 'never' && quiet) {
18
- Logger.println(colors.bold.yellow('The "never" exit-on strategy is not compatible with the "quiet" mode, it will exit once the deployment ends'));
23
+ Logger.println(
24
+ styleText(
25
+ ['bold', 'yellow'],
26
+ 'The "never" exit-on strategy is not compatible with the "quiet" mode, it will exit once the deployment ends',
27
+ ),
28
+ );
19
29
  }
20
30
  }
@@ -1,9 +1,10 @@
1
- import { join } from 'node:path';
2
1
  import { promises as fs } from 'node:fs';
2
+ import { join } from 'node:path';
3
3
 
4
- export function findPath (dir, name) {
4
+ export function findPath(dir, name) {
5
5
  const fullPath = join(dir, name);
6
- return fs.stat(fullPath)
6
+ return fs
7
+ .stat(fullPath)
7
8
  .then(() => dir)
8
9
  .catch((e) => {
9
10
  if (e.code === 'ENOENT' && dir !== '/') {
package/src/models/git.js CHANGED
@@ -1,25 +1,23 @@
1
+ import cliparse from 'cliparse';
2
+ import * as git from 'isomorphic-git';
3
+ import _ from 'lodash';
1
4
  import fs from 'node:fs';
2
5
  import path from 'node:path';
3
-
4
- import _ from 'lodash';
5
- import git from 'isomorphic-git';
6
- import * as http from './isomorphic-http-with-agent.js';
7
- import cliparse from 'cliparse';
8
6
  import { slugify } from '../lib/slugify.js';
9
- import { findPath } from './fs-utils.js';
10
7
  import { loadOAuthConf } from './configuration.js';
8
+ import { findPath } from './fs-utils.js';
9
+ import * as http from './isomorphic-http-with-agent.js';
11
10
 
12
- async function getRepo () {
11
+ async function getRepo() {
13
12
  try {
14
13
  const dir = await findPath('.', '.git');
15
14
  return { fs, dir, http };
16
- }
17
- catch (e) {
15
+ } catch {
18
16
  throw new Error('Could not find the .git folder.');
19
17
  }
20
18
  }
21
19
 
22
- async function onAuth () {
20
+ async function onAuth() {
23
21
  const tokens = await loadOAuthConf();
24
22
  return {
25
23
  username: tokens.token,
@@ -27,7 +25,7 @@ async function onAuth () {
27
25
  };
28
26
  }
29
27
 
30
- export async function addRemote (remoteName, url) {
28
+ export async function addRemote(remoteName, url) {
31
29
  const repo = await getRepo();
32
30
  const safeRemoteName = slugify(remoteName);
33
31
  const allRemotes = await git.listRemotes({ ...repo });
@@ -38,15 +36,14 @@ export async function addRemote (remoteName, url) {
38
36
  }
39
37
  }
40
38
 
41
- export async function resolveFullCommitId (commitId) {
39
+ export async function resolveFullCommitId(commitId) {
42
40
  if (commitId == null) {
43
41
  return null;
44
42
  }
45
43
  try {
46
44
  const repo = await getRepo();
47
45
  return await git.expandOid({ ...repo, oid: commitId });
48
- }
49
- catch (e) {
46
+ } catch (e) {
50
47
  if (e.code === 'ShortOidNotFound') {
51
48
  throw new Error(`Commit id ${commitId} is ambiguous`);
52
49
  }
@@ -54,7 +51,7 @@ export async function resolveFullCommitId (commitId) {
54
51
  }
55
52
  }
56
53
 
57
- export async function getRemoteCommit (remoteUrl) {
54
+ export async function getRemoteCommit(remoteUrl) {
58
55
  const repo = await getRepo();
59
56
  const remoteInfos = await git.getRemoteInfo({
60
57
  ...repo,
@@ -64,16 +61,16 @@ export async function getRemoteCommit (remoteUrl) {
64
61
  return _.get(remoteInfos, 'refs.heads.master');
65
62
  }
66
63
 
67
- export async function getFullBranch (branchName) {
64
+ export async function getFullBranch(branchName) {
68
65
  const repo = await getRepo();
69
66
  if (branchName === '') {
70
67
  const currentBranch = await git.currentBranch({ ...repo, fullname: true });
71
68
  return currentBranch || 'HEAD';
72
69
  }
73
70
  return git.expandRef({ ...repo, ref: branchName });
74
- };
71
+ }
75
72
 
76
- export async function getBranchCommit (refspec) {
73
+ export async function getBranchCommit(refspec) {
77
74
  const repo = await getRepo();
78
75
  const oid = await git.resolveRef({ ...repo, ref: refspec });
79
76
  // When a refspec refers to an annotated tag, the OID ref represents the annotation and not the commit directly,
@@ -82,7 +79,7 @@ export async function getBranchCommit (refspec) {
82
79
  return res.oid;
83
80
  }
84
81
 
85
- export async function isExistingTag (tag) {
82
+ export async function isExistingTag(tag) {
86
83
  const repo = await getRepo();
87
84
  const tags = await git.listTags({
88
85
  ...repo,
@@ -90,7 +87,7 @@ export async function isExistingTag (tag) {
90
87
  return tags.includes(tag);
91
88
  }
92
89
 
93
- export async function push (remoteUrl, branchRefspec, force) {
90
+ export async function push(remoteUrl, branchRefspec, force) {
94
91
  const repo = await getRepo();
95
92
  try {
96
93
  const push = await git.push({
@@ -105,8 +102,7 @@ export async function push (remoteUrl, branchRefspec, force) {
105
102
  throw new Error(push.errors.join(', '));
106
103
  }
107
104
  return push;
108
- }
109
- catch (e) {
105
+ } catch (e) {
110
106
  if (e.code === 'PushRejectedNonFastForward') {
111
107
  throw new Error('Push rejected because it was not a simple fast-forward. Use "--force" to override.');
112
108
  }
@@ -114,19 +110,18 @@ export async function push (remoteUrl, branchRefspec, force) {
114
110
  }
115
111
  }
116
112
 
117
- export function completeBranches () {
113
+ export function completeBranches() {
118
114
  return getRepo()
119
115
  .then((repo) => git.listBranches(repo))
120
116
  .then(cliparse.autocomplete.words);
121
117
  }
122
118
 
123
- export async function isShallow () {
119
+ export async function isShallow() {
124
120
  const { dir } = await getRepo();
125
121
  try {
126
122
  await fs.promises.access(path.join(dir, '.git', 'shallow'));
127
123
  return true;
128
- }
129
- catch (e) {
124
+ } catch {
130
125
  return false;
131
126
  }
132
127
  }
@@ -135,7 +130,7 @@ export async function isShallow () {
135
130
  * Check if the current directory is a git repository
136
131
  * @returns {Promise<boolean>}
137
132
  */
138
- export async function isInsideGitRepo () {
133
+ export async function isInsideGitRepo() {
139
134
  return getRepo()
140
135
  .then(() => true)
141
136
  .catch(() => false);
@@ -145,16 +140,15 @@ export async function isInsideGitRepo () {
145
140
  * Check if the current git working directory is clean
146
141
  * @returns {Promise<boolean>}
147
142
  */
148
- export async function isGitWorkingDirectoryClean () {
143
+ export async function isGitWorkingDirectoryClean() {
149
144
  const repo = await getRepo();
150
145
  const status = await git.statusMatrix({ ...repo });
151
- const isStatusEmpty = status
152
- .filter(([filepath, head, workdir]) => {
146
+ const isStatusEmpty =
147
+ status.filter(([filepath, head, workdir]) => {
153
148
  // WARNING: isomorphic-git does not support global gitignore so we filter hidden files and dirs to reduce the amount of false positives
154
149
  const isHidden = filepath.startsWith('.');
155
150
  const isCleverJson = filepath === '.clever.json';
156
151
  return (!isHidden || isCleverJson) && head !== workdir;
157
- })
158
- .length === 0;
152
+ }).length === 0;
159
153
  return isStatusEmpty;
160
154
  }
@@ -1,7 +1,7 @@
1
- import { Logger } from '../logger.js';
2
- import { sendToApi } from './send-to-api.js';
3
1
  import { getSummary } from '@clevercloud/client/esm/api/v2/user.js';
2
+ import { Logger } from '../logger.js';
4
3
  import { loadIdsCache, writeIdsCache } from './configuration.js';
4
+ import { sendToApi } from './send-to-api.js';
5
5
 
6
6
  /*
7
7
  This system uses a simplified representation of the summary to expose IDs links:
@@ -25,14 +25,13 @@ This system uses a simplified representation of the summary to expose IDs links:
25
25
  }
26
26
  */
27
27
 
28
- export async function resolveOwnerId (id) {
28
+ export async function resolveOwnerId(id) {
29
29
  return getIdFromCacheOrSummary((ids) => ids.owners[id]);
30
30
  }
31
31
 
32
- export async function resolveAddonId (id) {
33
-
32
+ export async function resolveAddonId(id) {
34
33
  const addonId = await getIdFromCacheOrSummary((ids) => {
35
- return (ids.addons[id] != null) ? ids.addons[id].addonId : null;
34
+ return ids.addons[id] != null ? ids.addons[id].addonId : null;
36
35
  });
37
36
 
38
37
  if (addonId != null) {
@@ -42,10 +41,9 @@ export async function resolveAddonId (id) {
42
41
  throw new Error(`Add-on ${id} does not exist`);
43
42
  }
44
43
 
45
- export async function resolveRealId (id) {
46
-
44
+ export async function resolveRealId(id) {
47
45
  const realId = await getIdFromCacheOrSummary((ids) => {
48
- return (ids.addons[id] != null) ? ids.addons[id].realId : null;
46
+ return ids.addons[id] != null ? ids.addons[id].realId : null;
49
47
  });
50
48
 
51
49
  if (realId != null) {
@@ -55,8 +53,7 @@ export async function resolveRealId (id) {
55
53
  throw new Error(`Add-on ${id} does not exist foo`);
56
54
  }
57
55
 
58
- async function getIdFromCacheOrSummary (callback) {
59
-
56
+ async function getIdFromCacheOrSummary(callback) {
60
57
  const idsFromCache = await loadIdsCache();
61
58
  const idFromCache = callback(idsFromCache);
62
59
  if (idFromCache != null) {
@@ -74,8 +71,7 @@ async function getIdFromCacheOrSummary (callback) {
74
71
  return null;
75
72
  }
76
73
 
77
- async function getIdsFromSummary () {
78
-
74
+ async function getIdsFromSummary() {
79
75
  const ids = {
80
76
  owners: {},
81
77
  addons: {},
@@ -83,10 +79,7 @@ async function getIdsFromSummary () {
83
79
 
84
80
  const summary = await getSummary().then(sendToApi);
85
81
 
86
- const owners = [
87
- summary.user,
88
- ...summary.organisations,
89
- ];
82
+ const owners = [summary.user, ...summary.organisations];
90
83
 
91
84
  for (const owner of owners) {
92
85
  for (const app of owner.applications) {
@@ -112,19 +105,21 @@ async function getIdsFromSummary () {
112
105
  * @throws {Error} if several add-ons are found
113
106
  * @returns {Object} The name, IDs and owner ID of the add-on { name, addonId, realId, ownerId }
114
107
  */
115
- export async function findAddonsByNameOrId (addonIdOrRealIdOrName, ownerNameOrId) {
108
+ export async function findAddonsByNameOrId(addonIdOrRealIdOrName, ownerNameOrId) {
116
109
  const summary = await getSummary().then(sendToApi);
117
110
 
118
- Logger.debug(`Searching for add-on '${addonIdOrRealIdOrName}' in ${summary.user.id} and ${summary.organisations.map((org) => org.id).join(', ')}`);
111
+ Logger.debug(
112
+ `Searching for add-on '${addonIdOrRealIdOrName}' in ${summary.user.id} and ${summary.organisations.map((org) => org.id).join(', ')}`,
113
+ );
119
114
  const candidates = [summary.user, ...summary.organisations]
120
115
  .flatMap((owner) => owner.addons.map((addon) => ({ addon, owner })))
121
116
  .filter(({ addon, owner }) => {
122
- const matchOwner = ownerNameOrId == null
123
- || owner.id === ownerNameOrId.orga_id
124
- || owner.name === ownerNameOrId.orga_name;
125
- const matchAddon = addon.name === addonIdOrRealIdOrName
126
- || addon.realId === addonIdOrRealIdOrName
127
- || addon.id === addonIdOrRealIdOrName;
117
+ const matchOwner =
118
+ ownerNameOrId == null || owner.id === ownerNameOrId.orga_id || owner.name === ownerNameOrId.orga_name;
119
+ const matchAddon =
120
+ addon.name === addonIdOrRealIdOrName ||
121
+ addon.realId === addonIdOrRealIdOrName ||
122
+ addon.id === addonIdOrRealIdOrName;
128
123
  return matchOwner && matchAddon;
129
124
  })
130
125
  .map(({ addon, owner }) => ({
@@ -149,24 +144,25 @@ export async function findAddonsByNameOrId (addonIdOrRealIdOrName, ownerNameOrId
149
144
  * @throws {Error} if several add-ons are found
150
145
  * @returns {Object} The name, IDs and owner ID of the add-on { name, addonId, realId, ownerId }
151
146
  */
152
- export async function findAddonsByAddonProvider (provider) {
147
+ export async function findAddonsByAddonProvider(provider) {
153
148
  const summary = await getSummary().then(sendToApi);
154
149
 
155
- Logger.debug(`Searching for ${provider} add-ons in ${summary.user.id} and ${summary.organisations.map((org) => org.id).join(', ')}`);
156
- const candidates = [summary.user, ...summary.organisations]
157
- .flatMap((owner) => {
158
- return owner.addons
159
- .filter((addon) => addon.providerId === provider)
160
- .map((addon) => {
161
- return {
162
- name: addon.name,
163
- addonId: addon.id,
164
- realId: addon.realId,
165
- ownerId: owner.id,
166
- ownerName: owner.name,
167
- };
168
- });
169
- });
150
+ Logger.debug(
151
+ `Searching for ${provider} add-ons in ${summary.user.id} and ${summary.organisations.map((org) => org.id).join(', ')}`,
152
+ );
153
+ const candidates = [summary.user, ...summary.organisations].flatMap((owner) => {
154
+ return owner.addons
155
+ .filter((addon) => addon.providerId === provider)
156
+ .map((addon) => {
157
+ return {
158
+ name: addon.name,
159
+ addonId: addon.id,
160
+ realId: addon.realId,
161
+ ownerId: owner.id,
162
+ ownerName: owner.name,
163
+ };
164
+ });
165
+ });
170
166
 
171
167
  Logger.debug(`Found ${candidates.length} candidate(s) for provider ${provider}:`);
172
168
  for (const candidate of candidates) {
@@ -1,4 +1,4 @@
1
- import isomotphicHttp from 'isomorphic-git/http/node/index.js';
1
+ import * as git from 'isomorphic-git/http/node';
2
2
  import https from 'node:https';
3
3
 
4
4
  // We use our own HTTP plugin, so we can customize the agent used for requests and configure a long timeout (default is 5 seconds).
@@ -8,6 +8,6 @@ const agent = new https.Agent({
8
8
  timeout: 10 * 60 * 1000,
9
9
  });
10
10
 
11
- export function request (params) {
12
- return isomotphicHttp.request({ ...params, agent });
11
+ export function request(params) {
12
+ return git.request({ ...params, agent });
13
13
  }
@@ -2,25 +2,24 @@
2
2
  * Helper to print a real JSON array with starting `[` and ending `]`
3
3
  */
4
4
  export class JsonArray {
5
- constructor () {
5
+ constructor() {
6
6
  this._isFirst = true;
7
7
  }
8
8
 
9
- open () {
9
+ open() {
10
10
  process.stdout.write('[\n');
11
11
  }
12
12
 
13
- push (log) {
13
+ push(log) {
14
14
  if (this._isFirst) {
15
15
  this._isFirst = false;
16
- }
17
- else {
16
+ } else {
18
17
  process.stdout.write(',\n');
19
18
  }
20
19
  process.stdout.write(` ${JSON.stringify(log)}`);
21
20
  }
22
21
 
23
- close () {
22
+ close() {
24
23
  process.stdout.write('\n]');
25
24
  }
26
25
  }