@adinsure-ops/ops-cli 5.4.2-rc1 → 5.5.0-rc1

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 (82) hide show
  1. package/README.md +140 -2
  2. package/bin/run.js +2 -6
  3. package/lib/command.base.d.ts +7 -1
  4. package/lib/command.base.jira.d.ts +23 -5
  5. package/lib/command.base.jira.js +47 -12
  6. package/lib/command.base.js +37 -8
  7. package/lib/command.download.d.ts +11 -0
  8. package/lib/command.download.js +27 -0
  9. package/lib/commands/config/get.d.ts +1 -1
  10. package/lib/commands/config/list.js +1 -1
  11. package/lib/commands/config/set.d.ts +2 -2
  12. package/lib/commands/config/set.js +2 -2
  13. package/lib/commands/config/unset.d.ts +1 -1
  14. package/lib/commands/docker/update-image-version.d.ts +31 -3
  15. package/lib/commands/docker/update-image-version.js +112 -6
  16. package/lib/commands/doctor.d.ts +1 -1
  17. package/lib/commands/download/client.d.ts +7 -20
  18. package/lib/commands/download/client.js +12 -47
  19. package/lib/commands/download/identity-server.d.ts +7 -20
  20. package/lib/commands/download/identity-server.js +12 -47
  21. package/lib/commands/download/jmeter.d.ts +3 -3
  22. package/lib/commands/download/jmeter.js +9 -11
  23. package/lib/commands/download/keycloak-scim.d.ts +4 -4
  24. package/lib/commands/download/keycloak-scim.js +9 -11
  25. package/lib/commands/download/platform.d.ts +7 -20
  26. package/lib/commands/download/platform.js +12 -47
  27. package/lib/commands/download/scheduler.d.ts +7 -20
  28. package/lib/commands/download/scheduler.js +12 -47
  29. package/lib/commands/download/server.d.ts +7 -20
  30. package/lib/commands/download/server.js +12 -47
  31. package/lib/commands/download/signalr.d.ts +7 -20
  32. package/lib/commands/download/signalr.js +12 -47
  33. package/lib/commands/download/studio.d.ts +12 -24
  34. package/lib/commands/download/studio.js +14 -48
  35. package/lib/commands/gitlab/get-tag-pipeline.d.ts +7 -7
  36. package/lib/commands/gitlab/get-tag-pipeline.js +5 -5
  37. package/lib/commands/gitlab/next-nightly-tag.d.ts +7 -7
  38. package/lib/commands/gitlab/next-nightly-tag.js +6 -6
  39. package/lib/commands/jira/issue.d.ts +4 -4
  40. package/lib/commands/jira/issue.js +2 -2
  41. package/lib/commands/jira/labels.d.ts +8 -9
  42. package/lib/commands/jira/labels.js +11 -10
  43. package/lib/commands/log/add.d.ts +10 -5
  44. package/lib/commands/log/add.js +42 -13
  45. package/lib/commands/log/generate.d.ts +6 -6
  46. package/lib/commands/log/generate.js +16 -8
  47. package/lib/commands/log/validate.js +2 -2
  48. package/lib/commands/login.d.ts +25 -5
  49. package/lib/commands/login.js +162 -40
  50. package/lib/commands/login.ru.d.ts +2 -2
  51. package/lib/commands/login.ru.js +1 -1
  52. package/lib/commands/npm/check-publish.d.ts +4 -4
  53. package/lib/commands/npm/check-publish.js +1 -1
  54. package/lib/commands/npm/dependency-update.d.ts +17 -4
  55. package/lib/commands/npm/dependency-update.js +64 -41
  56. package/lib/commands/npm/publish.d.ts +5 -5
  57. package/lib/commands/npm/publish.js +2 -2
  58. package/lib/commands/nuget/dependency-update.d.ts +3 -3
  59. package/lib/commands/prepare-content.d.ts +3 -3
  60. package/lib/commands/prepare-content.js +24 -41
  61. package/lib/commands/sql.d.ts +17 -17
  62. package/lib/commands/sql.js +23 -27
  63. package/lib/commands/translate.d.ts +8 -8
  64. package/lib/commands/translate.js +10 -8
  65. package/lib/commands/version.d.ts +10 -10
  66. package/lib/commands/version.js +6 -7
  67. package/lib/lib/command.d.ts +5 -3
  68. package/lib/lib/command.js +44 -44
  69. package/lib/lib/config.js +1 -1
  70. package/lib/lib/gitlab.d.ts +3 -1
  71. package/lib/lib/gitlab.js +13 -7
  72. package/lib/lib/http.d.ts +37 -0
  73. package/lib/lib/http.js +278 -0
  74. package/lib/lib/npm.d.ts +7 -4
  75. package/lib/lib/npm.js +15 -6
  76. package/lib/lib/npmrc.js +3 -3
  77. package/lib/lib/yarnrc.js +3 -3
  78. package/lib/security/cache.js +1 -1
  79. package/lib/security/context.d.ts +10 -8
  80. package/lib/security/context.js +49 -64
  81. package/oclif.manifest.json +533 -532
  82. package/package.json +71 -62
@@ -1,10 +1,11 @@
1
- /// <reference types="node" />
2
- import { ParsedUrlQuery } from 'querystring';
1
+ import { ParsedUrlQuery } from 'node:querystring';
2
+ import HttpClient from '../lib/http.js';
3
3
  /**
4
4
  * Security context that keeps track of current authentication token.
5
5
  * It's not recommended you instantiate this class on your own but rather inherit your commands from [[CommandBase]].
6
6
  */
7
7
  export default class SecurityContext {
8
+ private readonly http;
8
9
  private readonly clientId;
9
10
  private readonly devopsResourceId;
10
11
  private readonly managementCoreWindowsNet;
@@ -25,7 +26,7 @@ export default class SecurityContext {
25
26
  * Initializes [[SecurityContext]] with config directory where access token JSON will be stored.
26
27
  * @param configDir Directory where CLI configuration is stored
27
28
  */
28
- constructor(configDir: string);
29
+ constructor(configDir: string, http?: HttpClient);
29
30
  /**
30
31
  * Get the accessTokenPath, as it is a private variable
31
32
  * @returns {string} Returns access token path
@@ -42,10 +43,10 @@ export default class SecurityContext {
42
43
  */
43
44
  getConfigPath(): string;
44
45
  /**
45
- * Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
46
+ * Generates a PKCE pair and builds the AAD sign-in URL for the interactive browser login.
47
+ * The PKCE verifier is kept for the following [[acquireToken]] call.
46
48
  *
47
- * @param code Authorization code used to fetch the token.
48
- * @returns [[Promise<TokenResponse>]]
49
+ * @returns Promise that resolves the authorization URL to open in the browser
49
50
  */
50
51
  getLoginUrl(): Promise<string>;
51
52
  /**
@@ -83,8 +84,9 @@ export default class SecurityContext {
83
84
  /**
84
85
  * Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
85
86
  *
86
- * @param query Authorization query used to fetch the token.
87
- * @returns [[Promise<TokenResponse>]]
87
+ * @param query Query of the AAD redirect: `code` and `client_info`, or `error` and `error_description`.
88
+ * @throws Error when the redirect carries an error, the PKCE verifier is missing or the code exchange fails
89
+ * @returns Promise that resolves the signed-in account's display name, username, or '' when neither is known
88
90
  */
89
91
  acquireToken(query: ParsedUrlQuery): Promise<string>;
90
92
  /**
@@ -1,11 +1,9 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { AuthError, ConfidentialClientApplication, CryptoProvider, InteractionRequiredAuthError, PublicClientApplication, } from '@azure/msal-node';
3
- import { reject } from 'lodash-es';
4
- import path from 'path';
5
- import fs from 'fs';
6
- import querystring from 'querystring';
3
+ import path from 'node:path';
4
+ import fs from 'node:fs';
7
5
  import LocalCachePlugin from './cache.js';
8
- import axios from 'axios';
6
+ import HttpClient from '../lib/http.js';
9
7
  /**
10
8
  * Security context that keeps track of current authentication token.
11
9
  * It's not recommended you instantiate this class on your own but rather inherit your commands from [[CommandBase]].
@@ -15,7 +13,8 @@ export default class SecurityContext {
15
13
  * Initializes [[SecurityContext]] with config directory where access token JSON will be stored.
16
14
  * @param configDir Directory where CLI configuration is stored
17
15
  */
18
- constructor(configDir) {
16
+ constructor(configDir, http = new HttpClient()) {
17
+ this.http = http;
19
18
  this.clientId = 'bed40d09-53d7-4af8-bf63-3288658b65fb';
20
19
  this.devopsResourceId = '499b84ac-1321-427f-aa17-267ca6975798';
21
20
  this.managementCoreWindowsNet = 'https://management.core.windows.net//';
@@ -63,38 +62,25 @@ export default class SecurityContext {
63
62
  return this._accessConfigPath;
64
63
  }
65
64
  /**
66
- * Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
65
+ * Generates a PKCE pair and builds the AAD sign-in URL for the interactive browser login.
66
+ * The PKCE verifier is kept for the following [[acquireToken]] call.
67
67
  *
68
- * @param code Authorization code used to fetch the token.
69
- * @returns [[Promise<TokenResponse>]]
68
+ * @returns Promise that resolves the authorization URL to open in the browser
70
69
  */
71
70
  getLoginUrl() {
72
- return new Promise((resolve) => {
71
+ return __awaiter(this, void 0, void 0, function* () {
73
72
  // Generate PKCE Codes before starting the authorization flow
74
- this._cryptoProvider
75
- .generatePkceCodes()
76
- .then(({ verifier, challenge }) => {
77
- this._verifier = verifier;
78
- this._challenge = challenge;
79
- const authCodeUrlParameters = {
80
- scopes: [this.resource + '/.default', 'offline_access'],
81
- redirectUri: this.redirectUri,
82
- codeChallenge: this._challenge,
83
- codeChallengeMethod: 'S256',
84
- };
85
- // Get url to sign user in and consent to scopes needed for applicatio
86
- this._pca
87
- .getAuthCodeUrl(authCodeUrlParameters)
88
- .then((url) => {
89
- resolve(url);
90
- })
91
- .catch((error) => {
92
- reject(JSON.stringify(error));
93
- });
94
- })
95
- .catch((error) => {
96
- reject(error);
97
- });
73
+ const { verifier, challenge } = yield this._cryptoProvider.generatePkceCodes();
74
+ this._verifier = verifier;
75
+ this._challenge = challenge;
76
+ const authCodeUrlParameters = {
77
+ scopes: [this.resource + '/.default', 'offline_access'],
78
+ redirectUri: this.redirectUri,
79
+ codeChallenge: this._challenge,
80
+ codeChallengeMethod: 'S256',
81
+ };
82
+ // Get url to sign user in and consent to scopes needed for application
83
+ return this._pca.getAuthCodeUrl(authCodeUrlParameters);
98
84
  });
99
85
  }
100
86
  /**
@@ -155,7 +141,7 @@ export default class SecurityContext {
155
141
  forceCache: true,
156
142
  });
157
143
  if (tokenRespone === null) {
158
- throw new AuthError('Cannot retrieve user cache and use the refresh token!');
144
+ throw new AuthError('refresh_token_failed', '', 'Cannot retrieve user cache and use the refresh token!');
159
145
  }
160
146
  resolve(tokenRespone.accessToken);
161
147
  //eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -205,9 +191,7 @@ export default class SecurityContext {
205
191
  })
206
192
  .then((response) => {
207
193
  if (response) {
208
- const { accessToken } = response;
209
- console.log(accessToken);
210
- resolve(accessToken);
194
+ resolve(response.accessToken);
211
195
  }
212
196
  else {
213
197
  reject(new Error('Error getting token, please call `ops login`.'));
@@ -219,7 +203,7 @@ export default class SecurityContext {
219
203
  }
220
204
  }
221
205
  else {
222
- throw new Error('You are not authenticated, please call `ops login`.');
206
+ reject(new Error('You are not authenticated, please call `ops login`.'));
223
207
  }
224
208
  }));
225
209
  });
@@ -242,7 +226,7 @@ export default class SecurityContext {
242
226
  //eslint-disable-next-line @typescript-eslint/no-explicit-any
243
227
  }
244
228
  catch (err) {
245
- throw new Error(`Failed to retrieve GitLabRu token: ${err.message}`);
229
+ throw new Error(`Failed to retrieve GitLabRu token: ${err.message}`, { cause: err });
246
230
  }
247
231
  }
248
232
  getAADToken() {
@@ -287,7 +271,7 @@ export default class SecurityContext {
287
271
  // service=<registry>
288
272
  // tenant=<tenantId>
289
273
  // access_token=<aadAccessToken>
290
- const postData = querystring.stringify({
274
+ const postData = new URLSearchParams({
291
275
  grant_type: 'access_token',
292
276
  service: this.registry, // e.g., "adinsure.azurecr.io"
293
277
  tenant: this.tenantId, // e.g., "cdeb9156-219a-49e3-b414-f63acd298e9c"
@@ -296,7 +280,7 @@ export default class SecurityContext {
296
280
  // Define the URL for token exchange:
297
281
  const url = `https://${this.registry}/oauth2/exchange`;
298
282
  // Make the POST request with the appropriate headers.
299
- const response = yield axios.post(url, postData, {
283
+ const response = yield this.http.postForm(url, postData, {
300
284
  headers: {
301
285
  'Content-Type': 'application/x-www-form-urlencoded',
302
286
  },
@@ -311,20 +295,28 @@ export default class SecurityContext {
311
295
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
312
296
  }
313
297
  catch (error) {
314
- throw new Error('Failed to retrieve ACR token: ' + error.message);
298
+ throw new Error('Failed to retrieve ACR token: ' + error.message, { cause: error });
315
299
  }
316
300
  });
317
301
  }
318
302
  /**
319
303
  * Contacts authority server, fetches and saves the authentication token to be used in subsequent requests.
320
304
  *
321
- * @param query Authorization query used to fetch the token.
322
- * @returns [[Promise<TokenResponse>]]
305
+ * @param query Query of the AAD redirect: `code` and `client_info`, or `error` and `error_description`.
306
+ * @throws Error when the redirect carries an error, the PKCE verifier is missing or the code exchange fails
307
+ * @returns Promise that resolves the signed-in account's display name, username, or '' when neither is known
323
308
  */
324
309
  acquireToken(query) {
325
- return new Promise((resolve) => {
310
+ return __awaiter(this, void 0, void 0, function* () {
311
+ var _a, _b, _c, _d, _e, _f;
326
312
  if (this._verifier === null) {
327
- throw new Error(`PKCE verifier missing.`);
313
+ throw new Error('PKCE verifier missing.');
314
+ }
315
+ if (!query.code) {
316
+ const reason = (_b = (_a = query.error_description) !== null && _a !== void 0 ? _a : query.error) !== null && _b !== void 0 ? _b : 'Authorization code missing.';
317
+ // The redirect query is untrusted input; keep terminal control sequences out of the message.
318
+ // eslint-disable-next-line no-control-regex
319
+ throw new Error(`Login failed: ${String(reason).replace(/[\u0000-\u001f\u007f-\u009f]/g, '')}`);
328
320
  }
329
321
  // Add PKCE code verifier to token request object
330
322
  const tokenRequest = {
@@ -334,25 +326,18 @@ export default class SecurityContext {
334
326
  codeVerifier: this._verifier,
335
327
  clientInfo: query.client_info,
336
328
  };
337
- this._pca
338
- .acquireTokenByCode(tokenRequest)
339
- .then((token) => {
340
- var _a;
341
- if ((_a = token.account) === null || _a === void 0 ? void 0 : _a.name) {
342
- resolve(token.account.name);
343
- }
344
- })
345
- .catch((error) => {
329
+ try {
330
+ const token = yield this._pca.acquireTokenByCode(tokenRequest);
331
+ return (_f = (_d = (_c = token.account) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : (_e = token.account) === null || _e === void 0 ? void 0 : _e.username) !== null && _f !== void 0 ? _f : '';
332
+ }
333
+ catch (error) {
346
334
  if (error instanceof AuthError) {
347
- const authError = error;
348
- console.log(`Error name: + ${authError.name}`);
349
- console.log(`Error message: + ${authError.message}`);
350
- console.log(`Inner error message: + ${authError.errorMessage}`);
351
- console.log(`Error correlation id: + ${authError.correlationId}`);
352
- console.error();
335
+ // The message itself is reported by the caller; add only what helps trace the request.
336
+ console.error(`Error name: ${error.name}`);
337
+ console.error(`Error correlation id: ${error.correlationId}`);
353
338
  }
354
- throw new Error(error);
355
- });
339
+ throw error;
340
+ }
356
341
  });
357
342
  }
358
343
  /**