@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,12 +1,12 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { Flags } from '@oclif/core';
3
3
  import chalk from 'chalk';
4
- import fs from 'fs';
5
- import http from 'http';
4
+ import fs from 'node:fs';
5
+ import http from 'node:http';
6
6
  import open from 'open';
7
- import path from 'path';
8
- import url from 'url';
9
- import { execSync } from 'child_process';
7
+ import path from 'node:path';
8
+ import url from 'node:url';
9
+ import { execSync } from 'node:child_process';
10
10
  import CommandBase from '../command.base.js';
11
11
  import NpmRc from '../lib/npmrc.js';
12
12
  import YarnRc from '../lib/yarnrc.js';
@@ -33,7 +33,7 @@ class Login extends CommandBase {
33
33
  for (const registry of this.npmRegistries) {
34
34
  const registryUrl = new url.URL(registry);
35
35
  npmRc.set(`//${registryUrl.hostname}${registryUrl.pathname}:_authToken`, token);
36
- yarnRc.set("npmAuthToken", token);
36
+ yarnRc.set('npmAuthToken', token);
37
37
  }
38
38
  npmRc.save();
39
39
  yarnRc.save();
@@ -60,15 +60,14 @@ class Login extends CommandBase {
60
60
  try {
61
61
  execSync('docker --version', { stdio: 'ignore' });
62
62
  }
63
- catch (err) {
63
+ catch (_a) {
64
64
  this.error('Docker is not installed or not in PATH. Please install Docker first.', { exit: 1 });
65
65
  }
66
66
  // 2. Ensure the user is logged in (using your existing token retrieval logic)
67
67
  try {
68
68
  yield this.security.getToken();
69
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
69
  }
71
- catch (err) {
70
+ catch (_b) {
72
71
  this.error('User is not logged in. Please run "ops login" without --docker first.', { exit: 1 });
73
72
  }
74
73
  // 3. generate token from `adinsure.azurecr.io`
@@ -93,6 +92,147 @@ class Login extends CommandBase {
93
92
  }
94
93
  });
95
94
  }
95
+ /**
96
+ * Opens the system browser with the given URL. Separate method so tests can stub it.
97
+ */
98
+ openBrowser(loginUrl) {
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ let reported = false;
101
+ const fallback = () => {
102
+ if (!reported) {
103
+ reported = true;
104
+ this.printLoginUrl(loginUrl);
105
+ }
106
+ };
107
+ let browser;
108
+ try {
109
+ // open 11 rejects when the opener cannot be spawned (e.g. no `open`/`xdg-open` on PATH).
110
+ browser = yield open(loginUrl);
111
+ }
112
+ catch (_a) {
113
+ fallback();
114
+ return;
115
+ }
116
+ // Later process errors arrive as an 'error' event; unhandled, they crash the CLI.
117
+ browser.once('error', fallback);
118
+ // The opener can also start but fail, e.g. `xdg-open` without a configured browser.
119
+ browser.once('exit', (code) => {
120
+ if (code)
121
+ fallback();
122
+ });
123
+ });
124
+ }
125
+ printLoginUrl(loginUrl) {
126
+ this.log(`Could not open a browser. Open this URL to log in:\n${loginUrl}`);
127
+ }
128
+ /**
129
+ * Starts the local redirect server on port 3044.
130
+ * Resolves once the server is listening (rejects if it cannot bind, e.g. EADDRINUSE) with
131
+ * `authenticated`, which settles with the signed-in user's name or the code exchange error.
132
+ * The server is closed once the redirect has been handled or the server fails.
133
+ */
134
+ startAuthServer() {
135
+ return new Promise((listening, failed) => {
136
+ let resolve;
137
+ let reject;
138
+ const authenticated = new Promise((res, rej) => {
139
+ resolve = res;
140
+ reject = rej;
141
+ });
142
+ let handled = false;
143
+ const server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
144
+ var _a;
145
+ const requestUrl = new url.URL((_a = req.url) !== null && _a !== void 0 ? _a : '/', 'http://localhost:3044');
146
+ const query = requestUrl.searchParams;
147
+ // Only the AAD redirect counts; ignore e.g. favicon or duplicate requests.
148
+ if (handled || requestUrl.pathname !== '/' || !(query.has('code') || query.has('error'))) {
149
+ res.writeHead(404);
150
+ res.end();
151
+ return;
152
+ }
153
+ handled = true;
154
+ this.log(`${chalk.yellow('Acquiring your access token...')}`);
155
+ let status = 200;
156
+ let page = Login.responsePageContent;
157
+ let settle;
158
+ try {
159
+ const name = yield this.security.acquireToken(Object.fromEntries(Array.from(query.entries())));
160
+ settle = () => resolve(name);
161
+ }
162
+ catch (error) {
163
+ status = 400;
164
+ page = Login.failurePageContent;
165
+ settle = () => reject(error);
166
+ }
167
+ const finish = () => {
168
+ server.close();
169
+ server.closeAllConnections();
170
+ settle();
171
+ };
172
+ // The browser may have hung up during the exchange; its 'close' event has then already fired.
173
+ if (res.destroyed) {
174
+ finish();
175
+ return;
176
+ }
177
+ // Shut down only after the page is delivered (or the browser hangs up), so it is never cut off.
178
+ res.once('close', finish);
179
+ res.writeHead(status, { 'Content-Type': 'text/html' });
180
+ res.end(page);
181
+ }));
182
+ const portInUse = 'Port 3044 is already in use, so the login redirect cannot be received. ' +
183
+ 'Close the program using it (for example another `ops login`) and try again.';
184
+ const bindFailed = (error) => {
185
+ failed(error.code === 'EADDRINUSE' ? new Error(portInUse, { cause: error }) : error);
186
+ };
187
+ server.once('error', bindFailed);
188
+ server.listen(3044, () => {
189
+ server.off('error', bindFailed);
190
+ server.on('error', (error) => {
191
+ server.close();
192
+ server.closeAllConnections();
193
+ reject(error);
194
+ });
195
+ listening({ authenticated });
196
+ });
197
+ });
198
+ }
199
+ /**
200
+ * Interactive browser login: opens the AAD sign-in page and redeems the redirected authorization code.
201
+ * Any failure is reported and exits with code 1.
202
+ */
203
+ loginWithBrowser(npm) {
204
+ return __awaiter(this, void 0, void 0, function* () {
205
+ let name;
206
+ try {
207
+ const loginUrl = yield this.security.getLoginUrl();
208
+ const { authenticated } = yield this.startAuthServer();
209
+ // The redirect may arrive while the browser is still opening; it is awaited below.
210
+ authenticated.catch(() => undefined);
211
+ this.log(`${chalk.yellow('Note: Opening a browser for you to log in...')}`);
212
+ try {
213
+ yield this.openBrowser(loginUrl);
214
+ }
215
+ catch (_a) {
216
+ this.printLoginUrl(loginUrl);
217
+ }
218
+ name = yield authenticated;
219
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
+ }
221
+ catch (error) {
222
+ this.error(error, { exit: 1 });
223
+ }
224
+ this.log(name ? `Hello ${name}!` : `${chalk.green('Login Successful!')}`);
225
+ if (npm) {
226
+ try {
227
+ yield this.setNPM();
228
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
229
+ }
230
+ catch (error) {
231
+ this.error(error, { exit: 1 });
232
+ }
233
+ }
234
+ });
235
+ }
96
236
  run() {
97
237
  const _super = Object.create(null, {
98
238
  run: { get: () => super.run }
@@ -135,37 +275,7 @@ class Login extends CommandBase {
135
275
  }
136
276
  }
137
277
  else {
138
- this.log(`${chalk.yellow('Note: We have launched a browser for you to login.')}`);
139
- const loginUrl = yield this.security.getLoginUrl();
140
- yield open(loginUrl);
141
- const server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
142
- // First let the user know everything was OK
143
- res.writeHead(200, { 'Content-Type': 'text/html' });
144
- res.write(Login.responsePageContent);
145
- res.end();
146
- this.log(`${chalk.yellow('You have logged in successfully. Acquiring your access token...')}`);
147
- // Then let's acquire an authentication token from AAD
148
- try {
149
- const queryURL = new url.URL(req.url, 'http://localhost:3044').searchParams;
150
- const name = yield this.security.acquireToken(Object.fromEntries(Array.from(queryURL.entries())));
151
- this.log(`Hello ${name}!`);
152
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
153
- }
154
- catch (error) {
155
- this.error(error, { exit: false });
156
- }
157
- if (flags.npm) {
158
- try {
159
- yield this.setNPM();
160
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
- }
162
- catch (error) {
163
- this.error(error, { exit: false });
164
- }
165
- }
166
- server.close();
167
- }));
168
- server.listen(3044);
278
+ yield this.loginWithBrowser(flags.npm);
169
279
  }
170
280
  });
171
281
  }
@@ -214,4 +324,16 @@ Login.responsePageContent = `
214
324
  </script>
215
325
  </body>
216
326
  </html>`;
327
+ Login.failurePageContent = `
328
+ <!DOCTYPE html>
329
+ <html>
330
+ <head>
331
+ <title>ops-cli authenticate</title>
332
+ <link rel='icon' href='data:;base64,iVBORw0KGgo='>
333
+ </head>
334
+ <body>
335
+ <p><strong>Your login failed.</strong></p>
336
+ <p>See the ops-cli output in your terminal for details. You can close this page.</p>
337
+ </body>
338
+ </html>`;
217
339
  export default Login;
@@ -5,8 +5,8 @@ export default class LoginRu extends CommandBase<typeof LoginRu> {
5
5
  static usage: string;
6
6
  static examples: string[];
7
7
  static flags: {
8
- token: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
- force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
8
+ token: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
10
  };
11
11
  run(): Promise<void>;
12
12
  }
@@ -1,7 +1,7 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import { Flags } from '@oclif/core';
3
3
  import chalk from 'chalk';
4
- import fs from 'fs';
4
+ import fs from 'node:fs';
5
5
  import CommandBase from '../command.base.js';
6
6
  class LoginRu extends CommandBase {
7
7
  run() {
@@ -5,10 +5,10 @@ export default class NpmCheckPublish extends CommandBase<typeof NpmCheckPublish>
5
5
  static usage: string;
6
6
  static examples: string[];
7
7
  static flags: {
8
- package: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
- exclude: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
- version: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
- pat: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ package: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ version: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ pat: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  };
13
13
  checkPackagesExists(packages: NpmPackage[], allPackages: AzurePackageArray, version: string): Promise<void>;
14
14
  run(): Promise<void>;
@@ -36,7 +36,7 @@ class NpmCheckPublish extends CommandBase {
36
36
  _super.run.call(this);
37
37
  try {
38
38
  const { flags } = (yield this.parse(NpmCheckPublish));
39
- const npmContext = new NpmContext();
39
+ const npmContext = new NpmContext(this.http);
40
40
  ux.action.start('Parsing packages to check', undefined, { stdout: true });
41
41
  const packages = yield npmContext.packageList(this, flags.package, flags.exclude);
42
42
  ux.action.stop(`${chalk.green('done')}`);
@@ -5,12 +5,12 @@ export default class NpmDependencyUpdate extends CommandBase<typeof NpmDependenc
5
5
  static usage: string;
6
6
  static examples: string[];
7
7
  static args: {
8
- version: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
8
+ version: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
9
9
  };
10
10
  static flags: {
11
- filter: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[], import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
- exclude: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
13
- force: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
11
+ filter: import("@oclif/core/interfaces").OptionFlag<string[], import("@oclif/core/interfaces").CustomOptions>;
12
+ exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
14
  };
15
15
  /**
16
16
  * Update dependencies in package.json files for @adinsure packages
@@ -21,5 +21,18 @@ export default class NpmDependencyUpdate extends CommandBase<typeof NpmDependenc
21
21
  * @returns {Prmoise<void>} Void Promise
22
22
  */
23
23
  updateDependencies(newVersion: string, packages: NpmPackage[], force?: boolean, filter?: string[]): Promise<void>;
24
+ /**
25
+ * Serialize package.json data with the formatting of the original file,
26
+ * so only the updated versions show up in the diff
27
+ * @param data Package.json data
28
+ * @param original Original file content
29
+ * @returns {string} Formatted JSON
30
+ */
31
+ private formatJson;
32
+ /**
33
+ * Update versions of matching packages in a dependency group
34
+ * @returns {string[]} Names of updated packages
35
+ */
36
+ private updateDependencyGroup;
24
37
  run(): Promise<undefined>;
25
38
  }
@@ -21,53 +21,76 @@ class NpmDependencyUpdate extends CommandBase {
21
21
  // Find all package.json files that are not in node modules
22
22
  for (const path of packages) {
23
23
  try {
24
- const data = yield fs.readJSON(path.jsonPath);
25
- const updatedKeys = [];
26
- if (Object.prototype.hasOwnProperty.call(data, 'dependencies')) {
27
- for (const [key, value] of Object.entries(data.dependencies)) {
28
- const currentVersion = semver.valid(String(value));
29
- if (filter.some(pkg => minimatch(key, pkg))) {
30
- if (currentVersion && semver.gt(currentVersion, newVersion) && !force) {
31
- this.warn(`Lower of same version for dependency ${key} updated in file ${path.jsonPath}: ${newVersion} vs. ${currentVersion} is ${semver.gt(newVersion, currentVersion)}`);
32
- }
33
- else {
34
- data.dependencies[key] = newVersion;
35
- updatedKeys.push(key);
36
- }
37
- }
38
- }
39
- fs.writeFileSync(path.jsonPath, JSON.stringify(data, null, 4));
40
- if (updatedKeys.length > 0) {
41
- this.log(`Dependencies ${updatedKeys} updated in file ${path.jsonPath}`);
42
- }
24
+ const content = yield fs.readFile(path.jsonPath, 'utf8');
25
+ const bom = content.startsWith('\uFEFF') ? '\uFEFF' : '';
26
+ const data = JSON.parse(content.slice(bom.length));
27
+ const updatedDependencies = this.updateDependencyGroup(data.dependencies, 'dependency', newVersion, path.jsonPath, force, filter);
28
+ const updatedDevDependencies = this.updateDependencyGroup(data.devDependencies, 'devDependency', newVersion, path.jsonPath, force, filter);
29
+ if (updatedDependencies.length === 0 && updatedDevDependencies.length === 0) {
30
+ continue;
43
31
  }
44
- if (Object.prototype.hasOwnProperty.call(data, 'devDependencies')) {
45
- for (const [key, value] of Object.entries(data.devDependencies)) {
46
- const currentVersion = semver.valid(String(value));
47
- if (filter.some(pkg => minimatch(key, pkg))) {
48
- if (currentVersion && semver.gt(currentVersion, newVersion) && !force) {
49
- this.warn(`Lower of same version for devDependency ${key} updated in file ${path.jsonPath}: ${newVersion} vs. ${currentVersion} is ${semver.gt(newVersion, currentVersion)}`);
50
- }
51
- else {
52
- data.devDependencies[key] = newVersion;
53
- updatedKeys.push(key);
54
- }
55
- }
56
- }
57
- fs.writeFileSync(path.jsonPath, JSON.stringify(data, null, 4));
58
- if (updatedKeys.length > 0) {
59
- this.log(`devDependencies ${updatedKeys} updated in file ${path.jsonPath}`);
60
- }
32
+ yield fs.writeFile(path.jsonPath, bom + this.formatJson(data, content));
33
+ if (updatedDependencies.length > 0) {
34
+ this.log(`Dependencies ${updatedDependencies} updated in file ${path.jsonPath}`);
35
+ }
36
+ if (updatedDevDependencies.length > 0) {
37
+ this.log(`devDependencies ${updatedDevDependencies} updated in file ${path.jsonPath}`);
61
38
  }
62
39
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
40
  }
64
41
  catch (error) {
65
- this.warn(error.message);
66
- break;
42
+ this.warn(`Could not update ${path.jsonPath}: ${error.message}`);
67
43
  }
68
44
  }
69
45
  });
70
46
  }
47
+ /**
48
+ * Serialize package.json data with the formatting of the original file,
49
+ * so only the updated versions show up in the diff
50
+ * @param data Package.json data
51
+ * @param original Original file content
52
+ * @returns {string} Formatted JSON
53
+ */
54
+ formatJson(data, original) {
55
+ var _a, _b;
56
+ const lines = original.split('\n').filter(line => line.trim().length > 0);
57
+ // A minified or single-line file is kept on a single line
58
+ const indent = lines.length > 1 ? ((_b = (_a = /^([ \t]+)\S/m.exec(original)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : 4) : 0;
59
+ const newLine = original.endsWith('\n') ? (original.endsWith('\r\n') ? '\r\n' : '\n') : '';
60
+ let json = JSON.stringify(data, null, indent);
61
+ if (original.includes('\r\n')) {
62
+ json = json.replaceAll('\n', '\r\n');
63
+ }
64
+ return json + newLine;
65
+ }
66
+ /**
67
+ * Update versions of matching packages in a dependency group
68
+ * @returns {string[]} Names of updated packages
69
+ */
70
+ updateDependencyGroup(dependencies, type, newVersion, jsonPath, force, filter) {
71
+ const updatedKeys = [];
72
+ if (!dependencies) {
73
+ return updatedKeys;
74
+ }
75
+ for (const [key, value] of Object.entries(dependencies)) {
76
+ if (!filter.some(pkg => minimatch(key, pkg)) || value === newVersion) {
77
+ continue;
78
+ }
79
+ // Leave protocols such as workspace:, file:, link: or npm: aliases untouched
80
+ if (!semver.validRange(value)) {
81
+ this.warn(`Skipping ${type} ${key} in file ${jsonPath}: '${value}' is not a version or version range`);
82
+ continue;
83
+ }
84
+ const currentVersion = semver.minVersion(value);
85
+ if (currentVersion && semver.gt(currentVersion, newVersion) && !force) {
86
+ this.warn(`Skipping downgrade of ${type} ${key} in file ${jsonPath} from ${value} to ${newVersion}. Use --force to downgrade.`);
87
+ continue;
88
+ }
89
+ dependencies[key] = newVersion;
90
+ updatedKeys.push(key);
91
+ }
92
+ return updatedKeys;
93
+ }
71
94
  run() {
72
95
  const _super = Object.create(null, {
73
96
  run: { get: () => super.run }
@@ -76,13 +99,13 @@ class NpmDependencyUpdate extends CommandBase {
76
99
  _super.run.call(this);
77
100
  const { args, flags } = yield this.parse(NpmDependencyUpdate);
78
101
  const newVersion = semver.valid(args.version);
79
- const npmContext = new NpmContext();
102
+ const npmContext = new NpmContext(this.http);
80
103
  const command = new ChildProcessCommand();
81
104
  // Stop if version invalid
82
105
  if (!newVersion) {
83
106
  return this.error(`${chalk.red('Version in incorrect format')}`);
84
107
  }
85
- const packages = yield npmContext.packageList(this);
108
+ const packages = yield npmContext.packageList(this, ['**/*'], flags.exclude, false);
86
109
  try {
87
110
  yield this.updateDependencies(newVersion, packages, flags.force, flags.filter);
88
111
  ux.action.start(`running 'yarn install'`, undefined, {
@@ -123,7 +146,7 @@ NpmDependencyUpdate.flags = {
123
146
  multiple: true,
124
147
  }),
125
148
  exclude: Flags.string({
126
- description: 'exclude directories where to search for package.json',
149
+ description: 'names of packages whose package.json should not be updated',
127
150
  multiple: true,
128
151
  }),
129
152
  force: Flags.boolean({
@@ -5,11 +5,11 @@ export default class NpmPublish extends CommandBase<typeof NpmPublish> {
5
5
  static usage: string;
6
6
  static examples: string[];
7
7
  static flags: {
8
- package: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
- exclude: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
- version: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
- pat: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
- retry: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ package: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ version: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ pat: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ retry: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
13
13
  };
14
14
  private cp;
15
15
  publishPackage(pkg: NpmPackage, cmd?: string[]): Promise<{
@@ -1,7 +1,7 @@
1
1
  import { __asyncValues, __awaiter } from "tslib";
2
2
  import { Flags, ux } from '@oclif/core';
3
3
  import chalk from 'chalk';
4
- import { spawn } from 'child_process';
4
+ import { spawn } from 'node:child_process';
5
5
  import CommandBase from '../../command.base.js';
6
6
  import NpmContext from '../../lib/npm.js';
7
7
  class NpmPublish extends CommandBase {
@@ -148,7 +148,7 @@ class NpmPublish extends CommandBase {
148
148
  _super.run.call(this);
149
149
  try {
150
150
  const { flags } = yield this.parse(NpmPublish);
151
- const npmContext = new NpmContext();
151
+ const npmContext = new NpmContext(this.http);
152
152
  ux.action.start('Parsing packages to check', undefined, { stdout: true });
153
153
  const packages = yield npmContext.packageList(this, flags.package, flags.exclude);
154
154
  ux.action.stop(`${chalk.green('done')}`);
@@ -4,11 +4,11 @@ export default class NuGetDependencyUpdate extends CommandBase<typeof NuGetDepen
4
4
  static usage: string;
5
5
  static examples: string[];
6
6
  static args: {
7
- version: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
7
+ version: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
8
8
  };
9
9
  static flags: {
10
- filter: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
11
- exclude: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
10
+ filter: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ exclude: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  };
13
13
  /**
14
14
  * Update dependencies in csproj files for @adinsure packages
@@ -2,7 +2,7 @@ import CommandBase from '../command.base.js';
2
2
  interface Transformation {
3
3
  name: string;
4
4
  srcPath: string;
5
- transform(): void;
5
+ transform(): void | Promise<void>;
6
6
  }
7
7
  interface DotfileLine {
8
8
  prefix: string;
@@ -15,8 +15,8 @@ export default class PrepareContent extends CommandBase<typeof PrepareContent> {
15
15
  static usage: string;
16
16
  static examples: string[];
17
17
  static flags: {
18
- destination: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
19
- source: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
18
+ destination: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
19
+ source: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
20
  };
21
21
  parseDotfileLine(line: string, sourceDirectory: string): Promise<DotfileLine>;
22
22
  readDotfile(sourceDirectory: string): Promise<DotfileLine[]>;