@adinsure-ops/ops-cli 5.4.2 → 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.
- package/README.md +140 -2
- package/bin/run.js +2 -6
- package/lib/command.base.d.ts +7 -1
- package/lib/command.base.jira.d.ts +23 -5
- package/lib/command.base.jira.js +47 -12
- package/lib/command.base.js +37 -8
- package/lib/command.download.d.ts +11 -0
- package/lib/command.download.js +27 -0
- package/lib/commands/config/get.d.ts +1 -1
- package/lib/commands/config/list.js +1 -1
- package/lib/commands/config/set.d.ts +2 -2
- package/lib/commands/config/set.js +2 -2
- package/lib/commands/config/unset.d.ts +1 -1
- package/lib/commands/docker/update-image-version.d.ts +31 -3
- package/lib/commands/docker/update-image-version.js +112 -6
- package/lib/commands/doctor.d.ts +1 -1
- package/lib/commands/download/client.d.ts +7 -20
- package/lib/commands/download/client.js +12 -47
- package/lib/commands/download/identity-server.d.ts +7 -20
- package/lib/commands/download/identity-server.js +12 -47
- package/lib/commands/download/jmeter.d.ts +3 -3
- package/lib/commands/download/jmeter.js +9 -11
- package/lib/commands/download/keycloak-scim.d.ts +4 -4
- package/lib/commands/download/keycloak-scim.js +9 -11
- package/lib/commands/download/platform.d.ts +7 -20
- package/lib/commands/download/platform.js +12 -47
- package/lib/commands/download/scheduler.d.ts +7 -20
- package/lib/commands/download/scheduler.js +12 -47
- package/lib/commands/download/server.d.ts +7 -20
- package/lib/commands/download/server.js +12 -47
- package/lib/commands/download/signalr.d.ts +7 -20
- package/lib/commands/download/signalr.js +12 -47
- package/lib/commands/download/studio.d.ts +12 -24
- package/lib/commands/download/studio.js +14 -48
- package/lib/commands/gitlab/get-tag-pipeline.d.ts +7 -7
- package/lib/commands/gitlab/get-tag-pipeline.js +5 -5
- package/lib/commands/gitlab/next-nightly-tag.d.ts +7 -7
- package/lib/commands/gitlab/next-nightly-tag.js +6 -6
- package/lib/commands/jira/issue.d.ts +4 -4
- package/lib/commands/jira/issue.js +2 -2
- package/lib/commands/jira/labels.d.ts +8 -9
- package/lib/commands/jira/labels.js +11 -10
- package/lib/commands/log/add.d.ts +10 -5
- package/lib/commands/log/add.js +42 -13
- package/lib/commands/log/generate.d.ts +6 -6
- package/lib/commands/log/generate.js +16 -8
- package/lib/commands/log/validate.js +2 -2
- package/lib/commands/login.d.ts +25 -5
- package/lib/commands/login.js +162 -40
- package/lib/commands/login.ru.d.ts +2 -2
- package/lib/commands/login.ru.js +1 -1
- package/lib/commands/npm/check-publish.d.ts +4 -4
- package/lib/commands/npm/check-publish.js +1 -1
- package/lib/commands/npm/dependency-update.d.ts +17 -4
- package/lib/commands/npm/dependency-update.js +64 -41
- package/lib/commands/npm/publish.d.ts +5 -5
- package/lib/commands/npm/publish.js +2 -2
- package/lib/commands/nuget/dependency-update.d.ts +3 -3
- package/lib/commands/prepare-content.d.ts +3 -3
- package/lib/commands/prepare-content.js +24 -41
- package/lib/commands/sql.d.ts +17 -17
- package/lib/commands/sql.js +23 -27
- package/lib/commands/translate.d.ts +8 -8
- package/lib/commands/translate.js +10 -8
- package/lib/commands/version.d.ts +10 -10
- package/lib/commands/version.js +6 -7
- package/lib/lib/command.d.ts +5 -3
- package/lib/lib/command.js +44 -44
- package/lib/lib/config.js +1 -1
- package/lib/lib/gitlab.d.ts +3 -1
- package/lib/lib/gitlab.js +13 -7
- package/lib/lib/http.d.ts +37 -0
- package/lib/lib/http.js +278 -0
- package/lib/lib/npm.d.ts +7 -4
- package/lib/lib/npm.js +15 -6
- package/lib/lib/npmrc.js +3 -3
- package/lib/lib/yarnrc.js +3 -3
- package/lib/security/cache.js +1 -1
- package/lib/security/context.d.ts +10 -8
- package/lib/security/context.js +49 -64
- package/oclif.manifest.json +533 -532
- package/package.json +71 -62
package/lib/commands/login.js
CHANGED
|
@@ -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(
|
|
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 (
|
|
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 (
|
|
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.
|
|
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/
|
|
9
|
-
force: import("@oclif/core/
|
|
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
|
}
|
package/lib/commands/login.ru.js
CHANGED
|
@@ -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/
|
|
9
|
-
exclude: import("@oclif/core/
|
|
10
|
-
version: import("@oclif/core/
|
|
11
|
-
pat: import("@oclif/core/
|
|
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/
|
|
8
|
+
version: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
9
|
};
|
|
10
10
|
static flags: {
|
|
11
|
-
filter: import("@oclif/core/
|
|
12
|
-
exclude: import("@oclif/core/
|
|
13
|
-
force: import("@oclif/core/
|
|
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
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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: '
|
|
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/
|
|
9
|
-
exclude: import("@oclif/core/
|
|
10
|
-
version: import("@oclif/core/
|
|
11
|
-
pat: import("@oclif/core/
|
|
12
|
-
retry: import("@oclif/core/
|
|
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/
|
|
7
|
+
version: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
8
|
};
|
|
9
9
|
static flags: {
|
|
10
|
-
filter: import("@oclif/core/
|
|
11
|
-
exclude: import("@oclif/core/
|
|
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/
|
|
19
|
-
source: import("@oclif/core/
|
|
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[]>;
|